]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | <!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
2 | <html> | |
3 | <!-- | |
4 | (C) Copyright 2002-4 Robert Ramey - http://www.rrsd.com . | |
5 | Use, modification and distribution is subject to the Boost Software | |
6 | License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
7 | http://www.boost.org/LICENSE_1_0.txt) | |
8 | --> | |
9 | <head> | |
10 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> | |
11 | <link rel="stylesheet" type="text/css" href="../../../boost.css"> | |
12 | <link rel="stylesheet" type="text/css" href="style.css"> | |
13 | <title>Serialization - Derivation from an Existing Archive</title> | |
14 | </head> | |
15 | <body link="#0000ff" vlink="#800080"> | |
16 | <table border="0" cellpadding="7" cellspacing="0" width="100%" summary="header"> | |
17 | <tr> | |
18 | <td valign="top" width="300"> | |
19 | <h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../boost.png" border="0"></a></h3> | |
20 | </td> | |
21 | <td valign="top"> | |
22 | <h1 align="center">Serialization</h1> | |
23 | <h2 align="center">Derivation from an Existing Archive</h2> | |
24 | </td> | |
25 | </tr> | |
26 | </table> | |
27 | <hr> | |
28 | <dl class="page-index"> | |
29 | </dl> | |
30 | ||
31 | <h3>Log Archive</h3> | |
32 | It may happen that one wants to create a new archive class by derivation from one | |
33 | of the included ones. Included is a sample program that shows how to derive a | |
34 | new archive from one of the ones included with the library. The first example is | |
35 | <a href="../example/demo_log.cpp" target="demo_log_cpp"> | |
36 | demo_log.cpp</a>. | |
37 | <p> | |
38 | This derivation from the xml archive writes output in xml without the extra | |
39 | information required to read the data back into the application. It might be | |
40 | used to export one's data as simple xml for other applications or for logging | |
41 | data while debugging. | |
42 | <p> | |
43 | To this end it is derived from the included xml archive and the save functions for | |
44 | some types are specialized for this application. | |
45 | <p> | |
46 | The serialization library is | |
47 | implemented using the <b>C</b>uriously <b>R</b>ecurring <b>T</b>emplate | |
48 | <b>P</b>attern (<b>CRTP</b>). Also, all common code is factored out into | |
49 | separate modules to minimize code repetition. This makes derivation from | |
50 | an existing archive less straightforward than it would otherwise be. | |
51 | <p> | |
52 | This example illustrates several issues that have to be addressed when doing | |
53 | something like this | |
54 | <ol> | |
55 | <li><i>It is derived from</i> <code style="white-space: normal">xml_oarchive_impl<log_archive></code> | |
56 | <b>NOT</b> <code style="white-space: normal">xml_oarchive</code> <br> | |
57 | As described in the comments in | |
58 | <a href="../../../boost/archive/xml_oarchive.hpp" target="xml_oarchive_hpp">xml_oarchive.hpp</a>. | |
59 | <code style="white-space: normal">xml_oarchive</code> really a shorthand name for | |
60 | <code style="white-space: normal">xml_oarchive_impl<xml_oarchive></code>. So we should derive | |
61 | from <code style="white-space: normal">xml_oarchive_impl<log_archive></code> rather | |
62 | than <code style="white-space: normal">xml_oarchive</code>. | |
63 | <pre><code> | |
64 | class log_archive : | |
65 | // don't derive from xml_oarchive !!! | |
66 | public xml_oarchive_impl<log_archive> | |
67 | { | |
68 | ... | |
69 | </code></pre> | |
70 | <li><i>Note the</i> <code style="white-space: normal">log_archive</code> <i>between the</i> <> | |
71 | This is required so that base classes can downcast their <code style="white-space: normal">this</code> pointer | |
72 | to the most derived class. This is referred to as <b>C</b>uriously <b>R</b>ecurring | |
73 | <b>T</b>emplate <b>P</b>attern (<b>CRTP</b>) <a href="bibliography.html#11">[11]</a>. | |
74 | It is used to implement static polymorphism. | |
75 | <li><i>Base classes need to be explicitly given access to the derived class.</i> | |
76 | This can be done by making members public or by including friend declarations for | |
77 | the base classes. | |
78 | <pre><code> | |
79 | friend class detail::common_oarchive<log_archive>; | |
80 | friend class basic_xml_oarchive<log_archive>; | |
81 | friend class boost::serialization::save_access; | |
82 | </code></pre> | |
83 | ||
84 | <li><i></i>Reread <a target="detail" href="headers.html#archiveinternals">Archive Internals</a>. | |
85 | This describes the class hierarchy so that you know what to override. | |
86 | <li><i>Note the usage of PFTO.</i> Some compilers fail to provide support for | |
87 | partial function template ordering. The serialization library works around this by | |
88 | using <a target="detail" href="implementation.html#functiontemplateordering"> | |
89 | <b>P</b>artial <b>F</b>unction <b>T</b>emplate <b>O</b>rdering</a> in several places. | |
90 | This is done | |
91 | in several places, including the archive classes themselves. | |
92 | <li><i>Base class functions will usually need to be explicitly invoked.</i> | |
93 | We commonly specialize the function name <code style="white-space: normal">save_override</code> | |
94 | for saving primitives. Usage of a function name in a derived class | |
95 | "hides" similarly named functions of the base class. That is, | |
96 | function name overloading doesn't automatically | |
97 | include base classes. To address this, we can use: | |
98 | <pre><code> | |
99 | using xml_oarchive_impl<derived_t>::save; | |
100 | void save(const unsigned int t); | |
101 | ... | |
102 | </code></pre> | |
103 | which should work on conforming compilers. However, I have found | |
104 | that the following equivalent works on more compilers. | |
105 | <pre><code> | |
106 | // default fall through for any types not specified here | |
107 | template<class T> | |
108 | void save(const T & t){ | |
109 | xml_oarchive_impl<derived_t>::save(t); | |
110 | } | |
111 | void save(const unsigned int t); | |
112 | ... | |
113 | </code></pre> | |
114 | so it's what I use. | |
115 | <li><i>Template definitions of base classes may have to be explicitly instantiated.</i> | |
116 | The demo includes | |
117 | <pre><code> | |
118 | // explicitly instantiate for this type of binary stream | |
119 | #include <boost/archive/basic_binary_oprimitive.ipp> | |
120 | </code></pre> | |
121 | for just this purpose. Failure to include required template definitions | |
122 | will result in undefined symbol errors when the program is linked. | |
123 | <li><i>Without alteration, this class cannot be further derived from.</i><br> | |
124 | Base classes using <b>CRTP</b> must be templates with a parameter corresponding to | |
125 | the most derived class. As presented here, this class doesn't qualify, so | |
126 | it cannot be used as a base class. In order to derive further from this class, | |
127 | it would have to be reorganized along the lines of the original <code style="white-space: normal">xml_oarchive</code>. | |
128 | Specifically, it would look something like: | |
129 | <pre><code> | |
130 | template<class Archive> | |
131 | class log_archive_impl : | |
132 | // don't derive from xml_oarchive !!! | |
133 | public xml_oarchive_impl<Archive> | |
134 | { | |
135 | ... | |
136 | ); | |
137 | ||
138 | // do not derive from this class !!! | |
139 | class log_archive : | |
140 | public log_archive_impl<log_archive> | |
141 | { | |
142 | public: | |
143 | log_archive(std::ostream & os, unsigned int flags = 0) : | |
144 | log_archive_impl<xml_oarchive>(os, flags) | |
145 | {} | |
146 | }; | |
147 | </code></pre> | |
148 | ||
149 | </ol> | |
150 | ||
151 | <hr> | |
152 | <p><i>© Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 2002-2004. | |
153 | Distributed under the Boost Software License, Version 1.0. (See | |
154 | accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
155 | </i></p> | |
156 | </body> | |
157 | </html> |