| 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 - Serialization of Classes</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">Serializable Concept</h2> | 
|---|
| 24 |     </td> | 
|---|
| 25 |   </tr> | 
|---|
| 26 | </table> | 
|---|
| 27 | <hr> | 
|---|
| 28 | <dl class="page-index"> | 
|---|
| 29 |   <dt><a href="#primitiveoperators">Primitive Types</a> | 
|---|
| 30 |   <dt><a href="#classoperators">Class Types</a> | 
|---|
| 31 |   <dl class="page-index"> | 
|---|
| 32 |     <dt><a href="#member">Member Function</a> | 
|---|
| 33 |     <dt><a href="#free">Free Function</a> | 
|---|
| 34 |     <dl class="page-index"> | 
|---|
| 35 |       <dt><a href="#namespaces">Namespaces for Free Function Overrides</a> | 
|---|
| 36 |     </dl> | 
|---|
| 37 |     <dt><a href="#classmembers">Class Members</a> | 
|---|
| 38 |     <dl class="page-index"> | 
|---|
| 39 |       <dt><a href="#base">Base Classes</a> | 
|---|
| 40 |       <dt><a href="#const"><code style="white-space: normal">const</code> Members</a> | 
|---|
| 41 |       <dt><a href="#templates">Templates</a> | 
|---|
| 42 |     </dl> | 
|---|
| 43 |     <dt><a href="#versioning">Versioning</a> | 
|---|
| 44 |     <dt><a href="#splitting">Splitting <code style="white-space: normal">serialize</code> into  | 
|---|
| 45 |       <code style="white-space: normal">save/load</code></a> | 
|---|
| 46 |       <dl class="page-index"> | 
|---|
| 47 |         <dt><a href="#splittingmemberfunctions">Member Functions</a> | 
|---|
| 48 |         <dt><a href="#splittingfreefunctions">Free Functions</a> | 
|---|
| 49 |       </dl> | 
|---|
| 50 |   </dl> | 
|---|
| 51 |   <dt><a href="#pointers">Pointers</a> | 
|---|
| 52 |     <dl class="page-index"> | 
|---|
| 53 |       <dt><a href="#constructors">Non-Default Constructors</a> | 
|---|
| 54 |       <dt><a href="#derivedpointers">Pointers to Objects of Derived Classes</a> | 
|---|
| 55 |       <dl class="page-index"> | 
|---|
| 56 |         <dt><a href="#registration">Registration</a> | 
|---|
| 57 |         <dt><a href="#instantiation">Instantiation</a> | 
|---|
| 58 |         <dt><a href="#selectivetracking">Selective Tracking</a> | 
|---|
| 59 |         <dt><a href="#runtimecasting">Runtime Casting</a> | 
|---|
| 60 |       </dl> | 
|---|
| 61 |     </dl> | 
|---|
| 62 |   <dt><a href="#references">References</a> | 
|---|
| 63 |   <dt><a href="#arrays">Arrays</a> | 
|---|
| 64 |   <dt><a href="wrappers.html">Serialization Wrappers</a> | 
|---|
| 65 |   <dt><a href="traits.html">Class Serialization Traits</a> | 
|---|
| 66 |   <dt><a href="#models">Models - Serialization Implementations Included in the Library</a> | 
|---|
| 67 | </dl> | 
|---|
| 68 |  | 
|---|
| 69 | A type <code style="white-space: normal">T</code> is <strong>Serializable</strong>  | 
|---|
| 70 | if and only if one of the following is true: | 
|---|
| 71 | <ul> | 
|---|
| 72 |   <li>it is a primitive type.<br> | 
|---|
| 73 |     In this document, we use the term primitive type to mean | 
|---|
| 74 |     types whose data is simply saved/loaded to/from an archive | 
|---|
| 75 |     with no further processing.  Arithmetic (including characters),  | 
|---|
| 76 |     bool, enum and stl::string and stl::wstring types are primitive types.  Using  | 
|---|
| 77 |     <a target="detail" href="traits.html#Traits">serialization traits</a>, | 
|---|
| 78 |     any user type can also be designated as "primitive" | 
|---|
| 79 |     so that it is handled in this way. | 
|---|
| 80 |   <li>It is a class type and one of the following has been declared: | 
|---|
| 81 |     <ul> | 
|---|
| 82 |     <li>a class member function <code style="white-space: normal">serialize</code> | 
|---|
| 83 |     <li>a global function <code style="white-space: normal">serialize</code> | 
|---|
| 84 |     </ul> | 
|---|
| 85 |   <li>it is a pointer to a <strong>Serializable</strong> type. | 
|---|
| 86 |   <li>it is a reference to a <strong>Serializable</strong> type. | 
|---|
| 87 |   <li>it is an native C++ Array of <strong>Serializable</strong> type. | 
|---|
| 88 | </ul> | 
|---|
| 89 |  | 
|---|
| 90 | <h2><a name="primitiveoperators">Primitive Types</a></h2> | 
|---|
| 91 | The template operators &, <<, and >> of the archive classes  | 
|---|
| 92 | described above will generate code to save/load all primitive types | 
|---|
| 93 | to/from an archive.  This code will usually just add the | 
|---|
| 94 | data to the archive according to the archive format. | 
|---|
| 95 | For example, a four byte integer is appended to a binary archive | 
|---|
| 96 | as 4 binary bytes while a to a text archive it would be  | 
|---|
| 97 | rendered as a space followed by a string representation. | 
|---|
| 98 |  | 
|---|
| 99 | <h2><a name="classoperators">Class Types</a></h2> | 
|---|
| 100 | For class/struct types, the template operators &, <<, and >> | 
|---|
| 101 | will generate code that invokes the programmer's serialization code for the | 
|---|
| 102 | particular data type.  There is no default.  An attempt to serialize a | 
|---|
| 103 | class/struct for which no serialization has been explicitly specified | 
|---|
| 104 | will result in a compile time error.  The serialiation of a class can | 
|---|
| 105 | be specified via either a class member function or a free funcation which | 
|---|
| 106 | takes a reference to an instance of the class as an argument. | 
|---|
| 107 |  | 
|---|
| 108 | <h3><a name="member">Member Function</a></h3> | 
|---|
| 109 | The serialization library invokes the following code to save or load a class instance | 
|---|
| 110 | to/from and archive. | 
|---|
| 111 | <pre><code> | 
|---|
| 112 | template<class Archive, class T> | 
|---|
| 113 | inline void serialize( | 
|---|
| 114 |     Archive & ar,  | 
|---|
| 115 |     T & t,  | 
|---|
| 116 |     const unsigned int file_version | 
|---|
| 117 | ){ | 
|---|
| 118 |     // invoke member function for class T | 
|---|
| 119 |     t.serialize(ar, file_version); | 
|---|
| 120 | } | 
|---|
| 121 | </code></pre> | 
|---|
| 122 | That is, the default definition of template <code style="white-space: normal">serialize</code>  | 
|---|
| 123 | presumes the existence of a class member function template of the following  | 
|---|
| 124 | signature: | 
|---|
| 125 | <pre><code> | 
|---|
| 126 | template<class Archive> | 
|---|
| 127 | void serialize(Archive &ar, const unsigned int version){ | 
|---|
| 128 |     ... | 
|---|
| 129 | } | 
|---|
| 130 | </code></pre> | 
|---|
| 131 | If such a member function is not declared, a compile time error will occur.  In order | 
|---|
| 132 | that the member function generated by this template can be called to | 
|---|
| 133 | append the data to an archive, it either must be public or the class must | 
|---|
| 134 | be made accessible to the serialization library by including: | 
|---|
| 135 | <pre><code> | 
|---|
| 136 | friend class boost::serialization::access; | 
|---|
| 137 | </code></pre> | 
|---|
| 138 | in the class definition.  This latter method should be preferred over the option | 
|---|
| 139 | of making member function public. This will prevent serialization functions from  | 
|---|
| 140 | being called from outside the library.  This is almost certainly an error.  Unfortunately, | 
|---|
| 141 | it may appear to function but fail in a way that is very difficult to find. | 
|---|
| 142 | <p> | 
|---|
| 143 | It may not be immediately obvious how this one template serves for both | 
|---|
| 144 | saving data to an archive as well as loading data from the archive. | 
|---|
| 145 | The key is that the <code style="white-space: normal">&</code> operator is  | 
|---|
| 146 | defined as <code style="white-space: normal"><<</code> | 
|---|
| 147 | for output archives and as <code style="white-space: normal">>></code> input archives.  The | 
|---|
| 148 | "polymorphic" behavior of the <code style="white-space: normal">&</code> permits the same template | 
|---|
| 149 | to be used for both save and load operations.  This is very convenient in that it | 
|---|
| 150 | saves a lot of typing and guarantees that the saving and loading of class | 
|---|
| 151 | data members are always in sync.  This is the key to the whole serialization | 
|---|
| 152 | system. | 
|---|
| 153 |  | 
|---|
| 154 | <h3><a name="free">Free Function</a></h3> | 
|---|
| 155 | Of course we're not restricted to using the default implementation described | 
|---|
| 156 | above. We can override the default one with our own.  Doing this will | 
|---|
| 157 | permit us to implement serialization of a class without altering | 
|---|
| 158 | the class definition itself.  We call this <strong>non-intrusive</strong> | 
|---|
| 159 | serialization.  Suppose our class is named <code style="white-space: normal">my_class</code>, the | 
|---|
| 160 | override would be specified as: | 
|---|
| 161 | <pre><code> | 
|---|
| 162 | // namespace selection | 
|---|
| 163 |  | 
|---|
| 164 | template<class Archive> | 
|---|
| 165 | inline void serialize( | 
|---|
| 166 |     Archive & ar,  | 
|---|
| 167 |     my_class & t,  | 
|---|
| 168 |     const unsigned int file_version | 
|---|
| 169 | ){ | 
|---|
| 170 |     ... | 
|---|
| 171 | } | 
|---|
| 172 | </code></pre> | 
|---|
| 173 |  | 
|---|
| 174 | Note that we have called this override "non-intrusive".  This is slightly | 
|---|
| 175 | inaccurate.  It does not require that the class have special functions, that | 
|---|
| 176 | it be derived from some common base class or any other fundamental design changes. | 
|---|
| 177 | However, it will require access to the class members that are to | 
|---|
| 178 | be saved and loaded.  If these members are <code style="white-space: normal">private</code>, it won't be | 
|---|
| 179 | possible to serialize them.  So in some instances, minor modifications to the | 
|---|
| 180 | class to be serialized will be necessary even when using this "non-intrusive" | 
|---|
| 181 | method.  In practice this may not be such a problem as many libraries  | 
|---|
| 182 | (E.G. STL) expose enough information to permit implementation of non-intrusive | 
|---|
| 183 | serialization with absolutly no changes to the library. | 
|---|
| 184 |  | 
|---|
| 185 | <h4><a name="namespaces">Namespaces for Free Function Overrides</a></h4> | 
|---|
| 186 | For maximum portability, include any free functions templates and definitions in the  | 
|---|
| 187 | namespace <code style="white-space: normal">boost::serialization</code>.  If portability is not a concern and the | 
|---|
| 188 | compiler being used supports ADL (Argument Dependent Lookup) the free functions and | 
|---|
| 189 | templates can be in any of the following namespaces: | 
|---|
| 190 | <ul> | 
|---|
| 191 | <li><code style="white-space: normal">boost::serialization</code> | 
|---|
| 192 | <li>namespace of the archive class | 
|---|
| 193 | <li>namespace of the type being serialized | 
|---|
| 194 | </ul> | 
|---|
| 195 | <p> | 
|---|
| 196 | Note that, at first glance, this suggestion may seem to be wrong for compilers which implement | 
|---|
| 197 | two phase lookup.  In fact, the serialization library used a perhaps overly clever  | 
|---|
| 198 | method to support this rule even for such compilers.  Those with an interest in studying | 
|---|
| 199 | this furter will find more information in  | 
|---|
| 200 | <a target=serialization_hpp href="../../../boost/serialization/serialization.hpp">serialization.hpp</a> | 
|---|
| 201 |  | 
|---|
| 202 | <h3><a name="classmembers">Serialization of Class Members</a></h3> | 
|---|
| 203 | Regardless of which of the above methods is used,  the body of the serialize function must | 
|---|
| 204 | specify the data to be saved/loaded by sequential application of the archive | 
|---|
| 205 | <code style="white-space: normal">operator &</code> to all the data members of the class. | 
|---|
| 206 | <pre><code> | 
|---|
| 207 | { | 
|---|
| 208 |     // save/load class member variables | 
|---|
| 209 |     ar & member1; | 
|---|
| 210 |     ar & member2; | 
|---|
| 211 | } | 
|---|
| 212 | </code></pre> | 
|---|
| 213 |  | 
|---|
| 214 | <h4><a name="base">Base Classes</a></h4> | 
|---|
| 215 | The header file  | 
|---|
| 216 | <a href="../../../boost/serialization/base_object.hpp" target="base_object_hpp"> | 
|---|
| 217 | base_object.hpp | 
|---|
| 218 | </a> | 
|---|
| 219 | includes the template: | 
|---|
| 220 | <pre><code> | 
|---|
| 221 | template<class Base, class Derived> | 
|---|
| 222 | Base & base_object(Derived &d); | 
|---|
| 223 | </code></pre> | 
|---|
| 224 | which should be used to create a reference to an object of the base | 
|---|
| 225 | which can be used as an argument to the archive serialization operators. | 
|---|
| 226 | So for a class of <strong>Serializable</strong> type | 
|---|
| 227 | <code style="white-space: normal">T</code> the base class state should be  | 
|---|
| 228 | serialized like this: | 
|---|
| 229 | <pre><code> | 
|---|
| 230 | { | 
|---|
| 231 |     // invoke serialization of the base class  | 
|---|
| 232 |     ar & boost::serialization::base_object<base_class_of_T>(*this); | 
|---|
| 233 |     // save/load class member variables | 
|---|
| 234 |     ar & member1; | 
|---|
| 235 |     ar & member2; | 
|---|
| 236 | } | 
|---|
| 237 | </code></pre> | 
|---|
| 238 | Resist the temptation to just cast <code style="white-space: normal">*this</code> to the base class. | 
|---|
| 239 | This might seem to work but may fail to invoke code necessary for | 
|---|
| 240 | proper serialization. | 
|---|
| 241 | <p> | 
|---|
| 242 | Note that this is <strong>NOT</strong> the same as calling the <code style="white-space: normal">serialize</code> | 
|---|
| 243 | function of the base class. This might seem to work but will circumvent | 
|---|
| 244 | certain code used for tracking of objects, and registering base-derived | 
|---|
| 245 | relationships and other bookkeeping that is required for the serialization | 
|---|
| 246 | system to function as designed.  For this reason, all <code style="white-space: normal">serialize</code> | 
|---|
| 247 | member functions should be <code style="white-space: normal">private</code>. | 
|---|
| 248 |  | 
|---|
| 249 | <h4><a name="const"><code style="white-space: normal">const</code> Members</a></h4> | 
|---|
| 250 | Saving <code style="white-space: normal">const</code> members to an archive  | 
|---|
| 251 | requires no special considerations. | 
|---|
| 252 | Loading <code style="white-space: normal">const</code> members can be addressed by using a | 
|---|
| 253 | <code style="white-space: normal">const_cast</code>: | 
|---|
| 254 | <pre><code> | 
|---|
| 255 |     ar & const_cast<T &>(t); | 
|---|
| 256 | </code></pre> | 
|---|
| 257 | Note that this violates the spirit and intention of the <code style="white-space: normal">const</code> | 
|---|
| 258 | keyword. <code style="white-space: normal">const</code> members are intialized when a class instance | 
|---|
| 259 | is constructed and not changed thereafter.  However, this may | 
|---|
| 260 | be most appropriate in many cases.  Ultimately, it comes down to  | 
|---|
| 261 | the question about what <code style="white-space: normal">const</code> means in the context | 
|---|
| 262 | of serialization.  | 
|---|
| 263 |  | 
|---|
| 264 | <h4><a name="templates"></a>Templates</h4> | 
|---|
| 265 | Implementation serialization for templates is exactly the same process  | 
|---|
| 266 | as for normal classes and requires no additional considerations.  Among | 
|---|
| 267 | other things, this implies that serialization of compositions of templates | 
|---|
| 268 | are automatically generated when required if serialization of the  | 
|---|
| 269 | component templates is defined.  For example, this library includes | 
|---|
| 270 | definition of serialization for <code style="white-space: normal">boost::shared_ptr<T></code> and for | 
|---|
| 271 | <code style="white-space: normal">std::list<T></code>. If I have defined serialization for my own | 
|---|
| 272 | class <code style="white-space: normal">my_t</code>, then serialization for  | 
|---|
| 273 | <code style="white-space: normal">std::list< boost::shared_ptr< my_t> ></code> is already available | 
|---|
| 274 | for use. | 
|---|
| 275 | <p> | 
|---|
| 276 | See for an example that shows how this idea might be implemented for your own | 
|---|
| 277 | class templates, see | 
|---|
| 278 | <a href="../example/demo_auto_ptr.cpp" target="demo_auto_ptr.cpp"> | 
|---|
| 279 | demo_auto_ptr.cpp</a>. | 
|---|
| 280 | This shows how non-intrusive serialization | 
|---|
| 281 | for the template <code style="white-space: normal">auto_ptr</code> from the standard library | 
|---|
| 282 | can be implemented. | 
|---|
| 283 | <p> | 
|---|
| 284 | A somewhat trickier addition of serialization to a standard template | 
|---|
| 285 | can be found in the example  | 
|---|
| 286 | <a href="../../../boost/serialization/shared_ptr.hpp" target="shared_ptr_hpp"> | 
|---|
| 287 | shared_ptr.hpp | 
|---|
| 288 | </a> | 
|---|
| 289 | <!-- | 
|---|
| 290 | Only the most minimal change to | 
|---|
| 291 | <code>shared_count.hpp</code> | 
|---|
| 292 | (to gain access to some private members) was necessary to achieve this. | 
|---|
| 293 | This should demonstrate how easy it is to non-intrusively | 
|---|
| 294 | implement serialization to any data type or template.  | 
|---|
| 295 | --> | 
|---|
| 296 | <p> | 
|---|
| 297 | In the specification of serialization for templates, its common | 
|---|
| 298 | to split <code style="white-space: normal">serialize</code>  | 
|---|
| 299 | into a <code style="white-space: normal">load/save</code> pair.  | 
|---|
| 300 | Note that the convenience macro described  | 
|---|
| 301 | <a href="#BOOST_SERIALIZATION_SPLIT_FREE">above</a> | 
|---|
| 302 | isn't helpful in these cases as the number and kind of | 
|---|
| 303 | template class arguments won't match those used when splitting | 
|---|
| 304 | <code style="white-space: normal">serialize</code> for a simple class.  Use the override | 
|---|
| 305 | syntax instead. | 
|---|
| 306 |  | 
|---|
| 307 | <h3><a name="versioning">Versioning</a></h3> | 
|---|
| 308 | It will eventually occur that class definitions change after archives have | 
|---|
| 309 | been created. When a class instance is saved, the current version | 
|---|
| 310 | in included in the class information stored in the archive.  When the class instance | 
|---|
| 311 | is loaded from the archive, the original version number is passed as an | 
|---|
| 312 | argument to the loading function.  This permits the load function to include | 
|---|
| 313 | logic to accommodate older definitions for the class and reconcile them | 
|---|
| 314 | with latest version.  Save functions always save the current version.  So this | 
|---|
| 315 | results in automatically converting older format archives to the newest versions. | 
|---|
| 316 | Version numbers are maintained independently for each class.  This results in  | 
|---|
| 317 | a simple system for permitting access to older files and conversion of same. | 
|---|
| 318 | The current version of the class is assigned as a | 
|---|
| 319 | <a href="traits.html">Class Serialization Trait</a> described later in this manual. | 
|---|
| 320 | <pre><code> | 
|---|
| 321 | { | 
|---|
| 322 |     // invoke serialization of the base class  | 
|---|
| 323 |     ar & boost::serialization::base_object<base_class_of_T>(*this); | 
|---|
| 324 |     // save/load class member variables | 
|---|
| 325 |     ar & member1; | 
|---|
| 326 |     ar & member2; | 
|---|
| 327 |     // if its a recent version of the class | 
|---|
| 328 |     if(1 < file_version) | 
|---|
| 329 |         // save load recently added class members | 
|---|
| 330 |         ar & member3; | 
|---|
| 331 | } | 
|---|
| 332 | </code></pre> | 
|---|
| 333 |  | 
|---|
| 334 | <h3><a name="splitting">Splitting <code style="white-space: normal">serialize</code> into Save/Load</a></h3> | 
|---|
| 335 | There are times when it is inconvenient to use the same | 
|---|
| 336 | template for both save and load functions.  For example, this might occur if versioning | 
|---|
| 337 | gets complex.   | 
|---|
| 338 |  | 
|---|
| 339 | <h4><a name="splittingmemberfunctions">Splitting Member Functions</a></h4> | 
|---|
| 340 | For member functions this can be addressed by including | 
|---|
| 341 | the header file <a href="../../../boost/serialization/split_member.hpp" target="split_member_hpp"> | 
|---|
| 342 | boost/serialization/split_member.hpp</a> including code like this in the class: | 
|---|
| 343 | <pre><code> | 
|---|
| 344 | template<class Archive> | 
|---|
| 345 | void save(Archive & ar, const unsigned int version) const | 
|---|
| 346 | { | 
|---|
| 347 |     // invoke serialization of the base class  | 
|---|
| 348 |     ar << boost::serialization::base_object<const base_class_of_T>(*this); | 
|---|
| 349 |     ar << member1; | 
|---|
| 350 |     ar << member2; | 
|---|
| 351 |     ar << member3; | 
|---|
| 352 | } | 
|---|
| 353 |  | 
|---|
| 354 | template<class Archive> | 
|---|
| 355 | void load(Archive & ar, const unsigned int version) | 
|---|
| 356 | { | 
|---|
| 357 |     // invoke serialization of the base class  | 
|---|
| 358 |     ar >> boost::serialization::base_object<base_class_of_T>(*this); | 
|---|
| 359 |     ar >> member1; | 
|---|
| 360 |     ar >> member2; | 
|---|
| 361 |     if(version > 0) | 
|---|
| 362 |         ar >> member3; | 
|---|
| 363 | } | 
|---|
| 364 |  | 
|---|
| 365 | template<class Archive> | 
|---|
| 366 | void serialize( | 
|---|
| 367 |     Archive & ar, | 
|---|
| 368 |     const unsigned int file_version  | 
|---|
| 369 | ){ | 
|---|
| 370 |     boost::serialization::split_member(ar, *this, file_version); | 
|---|
| 371 | } | 
|---|
| 372 | </code></pre> | 
|---|
| 373 | This splits the serialization into two separate functions <code style="white-space: normal">save</code> | 
|---|
| 374 | and <code style="white-space: normal">load</code>.  Since the new <code style="white-space: normal">serialize</code> template | 
|---|
| 375 | is always the same it can be generated by invoking the macro | 
|---|
| 376 | BOOST_SERIALIZATION_SPLIT_MEMBER() defined in the header file | 
|---|
| 377 | <a href="../../../boost/serialization/split_member.hpp" target="split_member_hpp"> | 
|---|
| 378 | boost/serialization/split_member.hpp | 
|---|
| 379 | </a>. | 
|---|
| 380 | So the entire <code style="white-space: normal">serialize</code> function above can be replaced with: | 
|---|
| 381 | <pre><code> | 
|---|
| 382 | BOOST_SERIALIZATION_SPLIT_MEMBER() | 
|---|
| 383 | </code></pre> | 
|---|
| 384 | <h4><a name="splittingfreefunctions">Splitting Free Functions</a></h4> | 
|---|
| 385 | The situation is same for non-intrusive serialization with the free | 
|---|
| 386 | <code style="white-space: normal">serialize</code> function template. | 
|---|
| 387 |  | 
|---|
| 388 | <a name="BOOST_SERIALIZATION_SPLIT_FREE"> | 
|---|
| 389 | To use <code style="white-space: normal">save</code> and  | 
|---|
| 390 | <code style="white-space: normal">load</code> function templates rather than  | 
|---|
| 391 | <code style="white-space: normal">serialize</code>: | 
|---|
| 392 | <pre><code> | 
|---|
| 393 | namespace boost { namespace serialization { | 
|---|
| 394 | template<class Archive> | 
|---|
| 395 | void save(Archive & ar, const my_class & t, unsigned int version) | 
|---|
| 396 | { | 
|---|
| 397 |     ... | 
|---|
| 398 | } | 
|---|
| 399 | template<class Archive> | 
|---|
| 400 | void load(Archive & ar, my_class & t, unsigned int version) | 
|---|
| 401 | { | 
|---|
| 402 |     ... | 
|---|
| 403 | } | 
|---|
| 404 | }} | 
|---|
| 405 | </code></pre> | 
|---|
| 406 | include the header file  | 
|---|
| 407 | <a href="../../../boost/serialization/split_free.hpp" target="split_free_hpp"> | 
|---|
| 408 | boost/serialization/split_free.hpp | 
|---|
| 409 | </a>. | 
|---|
| 410 | and override the free <code style="white-space: normal">serialize</code> function template: | 
|---|
| 411 | <pre><code> | 
|---|
| 412 | namespace boost { namespace serialization { | 
|---|
| 413 | template<class Archive> | 
|---|
| 414 | inline void serialize( | 
|---|
| 415 |     Archive & ar, | 
|---|
| 416 |     my_class & t, | 
|---|
| 417 |     const unsigned int file_version | 
|---|
| 418 | ){ | 
|---|
| 419 |     split_free(ar, t, file_version);  | 
|---|
| 420 | } | 
|---|
| 421 | }} | 
|---|
| 422 | </code></pre> | 
|---|
| 423 | To shorten typing, the above template can be replaced with | 
|---|
| 424 | the macro: | 
|---|
| 425 | <pre><code> | 
|---|
| 426 | BOOST_SERIALIZATION_SPLIT_FREE(my_class) | 
|---|
| 427 | </code></pre> | 
|---|
| 428 |  | 
|---|
| 429 | Note that although the functionality to split the <code style="white-space: normal"> | 
|---|
| 430 | serialize</code> function into <code style="white-space: normal">save/load</code> | 
|---|
| 431 | has been provided, the usage of the <code style="white-space: normal">serialize</code> | 
|---|
| 432 | function with the corresponding <code style="white-space: normal">&</code> operator | 
|---|
| 433 | is preferred.  The key to the serialization implementation is that objects are saved  | 
|---|
| 434 | and loaded in exactly the same sequence.  Using the <code style="white-space: normal">&</code>  | 
|---|
| 435 | operator and <code style="white-space: normal">serialize</code> | 
|---|
| 436 | function guarantees that this is always the case and will minimize the | 
|---|
| 437 | occurence of hard to find errors related to synchronization of  | 
|---|
| 438 | <code style="white-space: normal">save</code> and <code style="white-space: normal">load</code>  | 
|---|
| 439 | functions. | 
|---|
| 440 |  | 
|---|
| 441 | <h2><a name="pointeroperators">Pointers</a></h2> | 
|---|
| 442 | A pointer to any class instance can be serialized with any of the archive  | 
|---|
| 443 | save/load operators. | 
|---|
| 444 | <p> | 
|---|
| 445 | To properly save and restore an object through a pointer the | 
|---|
| 446 | following situations must be addressed: | 
|---|
| 447 | <ol> | 
|---|
| 448 |     <li>If the same object is saved multiple times through different | 
|---|
| 449 |     pointers, only one copy of the object need be saved. | 
|---|
| 450 |     <li>If an object is loaded multiple times through different pointers, | 
|---|
| 451 |     only one new object should be created and all returned pointers | 
|---|
| 452 |     should point to it. | 
|---|
| 453 |     <li>The system must detect the case where an object is first | 
|---|
| 454 |     saved through a pointer then the object itself is saved. | 
|---|
| 455 |     Without taking extra precautions, loading would result in the | 
|---|
| 456 |     creation of multiple copies of the original object. This system detects | 
|---|
| 457 |     this case when saving and throws an exception - see below. | 
|---|
| 458 |     <li>An object of a derived class may be stored through a | 
|---|
| 459 |     pointer to the base class. The true type of the object must | 
|---|
| 460 |     be determined and saved. Upon restoration the correct type | 
|---|
| 461 |     must be created and its address correctly cast to the base | 
|---|
| 462 |     class. That is, polymorphic pointers have to be considered. | 
|---|
| 463 |     <li>NULL pointers must be dectected when saved and restored | 
|---|
| 464 |     to NULL when deserialized. | 
|---|
| 465 | </ol> | 
|---|
| 466 |  | 
|---|
| 467 | This serialization library addresses all of the above | 
|---|
| 468 | considerations. The process of saving and loading an object | 
|---|
| 469 | through a pointer is non-trivial. It can be summarized as | 
|---|
| 470 | follows: | 
|---|
| 471 | <p>Saving a pointer: | 
|---|
| 472 | <ol> | 
|---|
| 473 |     <li>determine the true type of the object being pointed to. | 
|---|
| 474 |     <li>write a special tag to the archive | 
|---|
| 475 |     <li>if the object pointed to has not already been written | 
|---|
| 476 |     to the archive, do so now | 
|---|
| 477 | </ol> | 
|---|
| 478 | Loading a pointer: | 
|---|
| 479 | <ol> | 
|---|
| 480 |     <li>read a tag from the archive. | 
|---|
| 481 |     <li>determine the type of object to be created | 
|---|
| 482 |     <li>if the object has already been loaded, return it's address. | 
|---|
| 483 |     <li>otherwise, create a new instance of the object | 
|---|
| 484 |     <li>read the data back in using the operators described above | 
|---|
| 485 |     <li>return the address of the newly created object. | 
|---|
| 486 | </ol> | 
|---|
| 487 |  | 
|---|
| 488 | Given that class instances are saved/loaded to/from the archive | 
|---|
| 489 | only once, regardless of how many times they are serialized with | 
|---|
| 490 | the <code style="white-space: normal"><<</code>  | 
|---|
| 491 | and <code style="white-space: normal">>></code> operators | 
|---|
| 492 | <ul> | 
|---|
| 493 |     <li>Loading the same pointer object multiple times | 
|---|
| 494 |     results in only one object being created, thereby replicating | 
|---|
| 495 |     the original pointer configuration.  | 
|---|
| 496 |     <li>Structures such as collections of polymorphic pointers, | 
|---|
| 497 |     are handled with no special effort on the part of users of this library. | 
|---|
| 498 | </ul> | 
|---|
| 499 | Serialization of pointers of derived types through a pointer to the | 
|---|
| 500 | base class may require a little extra "help".  Also, the programmer | 
|---|
| 501 | may desire to modify the process described above for his own reasons. | 
|---|
| 502 | For example, it might be desired to suppress the tracking of objects | 
|---|
| 503 | as it is known a priori that the application in question can never | 
|---|
| 504 | create duplicate objects.  Serialization of pointers can be "fine tuned" | 
|---|
| 505 | via the specification of <a target="detail" href="traits.html#Traits">Class Serialization Traits</a> | 
|---|
| 506 | as described in | 
|---|
| 507 | <a target="detail" href="special.html#derivedpointers"> | 
|---|
| 508 | another section of this manual | 
|---|
| 509 | </a> | 
|---|
| 510 |  | 
|---|
| 511 | <h3><a name="constructors">Non-Default Constructors</a></h3> | 
|---|
| 512 | Serialization of pointers is implemented in the library with code | 
|---|
| 513 | similar to the following: | 
|---|
| 514 | <pre><code> | 
|---|
| 515 | // load data required for construction and invoke constructor in place | 
|---|
| 516 | template<class Archive, class T> | 
|---|
| 517 | inline void load_construct_data( | 
|---|
| 518 |     Archive & ar, T * t, const unsigned int file_version | 
|---|
| 519 | ){ | 
|---|
| 520 |     // default just uses the default constructor to initialize | 
|---|
| 521 |     // previously allocated memory.  | 
|---|
| 522 |     ::new(t)T(); | 
|---|
| 523 | } | 
|---|
| 524 | </code></pre> | 
|---|
| 525 | The default <code style="white-space: normal">load_construct_data</code> invokes the | 
|---|
| 526 | default constructor "in-place" to initialize the memory. | 
|---|
| 527 | <p> | 
|---|
| 528 | If there is no such default constructor, the function templates | 
|---|
| 529 | <code style="white-space: normal">load_construct_data</code> and  | 
|---|
| 530 | perhaps <code style="white-space: normal">save_construct_data</code> | 
|---|
| 531 | will have to be overridden.  Here is a simple example: | 
|---|
| 532 | <pre><code> | 
|---|
| 533 | class my_class { | 
|---|
| 534 | private: | 
|---|
| 535 |     friend class boost::serialization::access; | 
|---|
| 536 |     int member; | 
|---|
| 537 |     template<class Archive> | 
|---|
| 538 |     void serialize(Archive &ar, const unsigned int file_version){ | 
|---|
| 539 |         ar & member; | 
|---|
| 540 |     } | 
|---|
| 541 | public: | 
|---|
| 542 |     my_class(int m) : | 
|---|
| 543 |         member(m) | 
|---|
| 544 |     {} | 
|---|
| 545 | }; | 
|---|
| 546 | </code></pre> | 
|---|
| 547 | the overrides would be: | 
|---|
| 548 | <pre><code> | 
|---|
| 549 | namespace boost { namespace serialization { | 
|---|
| 550 | template<class Archive> | 
|---|
| 551 | inline void save_construct_data( | 
|---|
| 552 |     Archive & ar, const my_class * t, const unsigned int file_version | 
|---|
| 553 | ){ | 
|---|
| 554 |     // save data required to construct instance | 
|---|
| 555 |     ar << t->member; | 
|---|
| 556 | } | 
|---|
| 557 |  | 
|---|
| 558 | template<class Archive> | 
|---|
| 559 | inline void load_construct_data( | 
|---|
| 560 |     Archive & ar, my_class * t, const unsigned int file_version | 
|---|
| 561 | ){ | 
|---|
| 562 |     // retrieve data from archive required to construct new instance | 
|---|
| 563 |     int m; | 
|---|
| 564 |     ar >> m; | 
|---|
| 565 |     // invoke inplace constructor to initialize instance of my_class | 
|---|
| 566 |     ::new(t)my_class(m); | 
|---|
| 567 | } | 
|---|
| 568 | }} // namespace ... | 
|---|
| 569 | </code></pre> | 
|---|
| 570 | In addition to the deserialization of pointers, these overrides are used | 
|---|
| 571 | in the deserialization of STL containers whose element type has no default | 
|---|
| 572 | constructor. | 
|---|
| 573 |  | 
|---|
| 574 | <h3><a name="derivedpointers">Pointers to Objects of Derived Classes</a></h3> | 
|---|
| 575 | <h4><a name="registration">Registration</a></h4> | 
|---|
| 576 | Consider the following: | 
|---|
| 577 | <pre><code> | 
|---|
| 578 | class base { | 
|---|
| 579 |     ... | 
|---|
| 580 | }; | 
|---|
| 581 | class derived_one : public base { | 
|---|
| 582 |     ... | 
|---|
| 583 | }; | 
|---|
| 584 | class derived_two : public base { | 
|---|
| 585 |     ... | 
|---|
| 586 | }; | 
|---|
| 587 | main(){ | 
|---|
| 588 |     ... | 
|---|
| 589 |     base *b; | 
|---|
| 590 |     ... | 
|---|
| 591 |     ar & b;  | 
|---|
| 592 | } | 
|---|
| 593 | </code></pre> | 
|---|
| 594 | When saving <code style="white-space: normal">b</code> what kind of object should be saved?  | 
|---|
| 595 | When loading <code style="white-space: normal">b</code> what kind of object should be created?  | 
|---|
| 596 | Should it be an object of class <code style="white-space: normal">derived_one</code>, | 
|---|
| 597 | <code style="white-space: normal">derived_two</code>, or maybe <code style="white-space: normal">base</code>? | 
|---|
| 598 | <p> | 
|---|
| 599 | It turns out that the kind of object serialized depends upon whether the base class | 
|---|
| 600 | (<code style="white-space: normal">base</code> in this case) is polymophic or not. | 
|---|
| 601 | If <code style="white-space: normal">base</code> is not polymorphic, that is if it has no | 
|---|
| 602 | virtual functions, then an object of the type <code style="white-space: normal">base</code> | 
|---|
| 603 | will be serialized. Information in any derived classes will be lost. If this is what is desired | 
|---|
| 604 | (it usually isn't) then no other effort is required. | 
|---|
| 605 | <p> | 
|---|
| 606 |  | 
|---|
| 607 | If the base class is polymorphic, an object of the most derived type | 
|---|
| 608 | (<code style="white-space: normal">derived_one</code> | 
|---|
| 609 | or <code style="white-space: normal">derived_two</code> | 
|---|
| 610 | in this case) will be serialized.  The question of which type of object is to be | 
|---|
| 611 | serialized is (almost) automatically handled by the library. | 
|---|
| 612 | <p> | 
|---|
| 613 | The system "registers" each class in an archive the first time an object of that | 
|---|
| 614 | class it is serialized and assigns a sequential number to it.  Next time an | 
|---|
| 615 | object of that class is serialized in that same archive, this number is written | 
|---|
| 616 | in the archive.  So every class is identified uniquely within the archive.   | 
|---|
| 617 | When the archive is read back in, each new sequence number is re-associated with  | 
|---|
| 618 | the class being read.  Note that this implies that "registration" has to occur | 
|---|
| 619 | during both save and load so that the class-integer table built on load | 
|---|
| 620 | is identical to the class-integer table built on save. In fact, the key to | 
|---|
| 621 | whole serialization system is that things are always saved and loaded in | 
|---|
| 622 | the same sequence.  This includes "registration". | 
|---|
| 623 | <p> | 
|---|
| 624 | Expanding our previous example: | 
|---|
| 625 | <pre><code> | 
|---|
| 626 | main(){ | 
|---|
| 627 |     derived_one d1; | 
|---|
| 628 |     derived_two d2: | 
|---|
| 629 |     ... | 
|---|
| 630 |     ar & d1; | 
|---|
| 631 |     ar & d2; | 
|---|
| 632 |     // A side effect of serialization of objects d1 and d2 is that | 
|---|
| 633 |     // the classes derived_one and derived_two become known to the archive. | 
|---|
| 634 |     // So subsequent serialization of those classes by base pointer works | 
|---|
| 635 |     // without any special considerations. | 
|---|
| 636 |     base *b; | 
|---|
| 637 |     ... | 
|---|
| 638 |     ar & b;  | 
|---|
| 639 | } | 
|---|
| 640 | </code></pre> | 
|---|
| 641 | When <code style="white-space: normal">b</code> is read it is | 
|---|
| 642 | preceded by a unique (to the archive) class identifier which | 
|---|
| 643 | has previously been related to class <code style="white-space: normal">derived_one</code> or | 
|---|
| 644 | <code style="white-space: normal">derived_two</code>. | 
|---|
| 645 | <p> | 
|---|
| 646 | If a derived class has NOT been automatically "registered" as described | 
|---|
| 647 | above, an <a target="detail" href="exceptions.html#unregistered_class"> | 
|---|
| 648 | <code style="white-space: normal">unregistered_class</code></a> exception  | 
|---|
| 649 | will be thrown when serialization is invoked. | 
|---|
| 650 | <p> | 
|---|
| 651 | This can be addressed by registering the derived class explicitly.  All archives are | 
|---|
| 652 | derived from a base class which implements the following template: | 
|---|
| 653 | <pre><code> | 
|---|
| 654 | template<class T> | 
|---|
| 655 | register_type(); | 
|---|
| 656 | </code></pre> | 
|---|
| 657 | So our problem could just as well be addressed by writing: | 
|---|
| 658 | <pre><code> | 
|---|
| 659 | main(){ | 
|---|
| 660 |     ... | 
|---|
| 661 |     ar.template register_type<derived_one>(); | 
|---|
| 662 |     ar.template register_type<derived_two>(); | 
|---|
| 663 |     base *b; | 
|---|
| 664 |     ... | 
|---|
| 665 |     ar & b;  | 
|---|
| 666 | } | 
|---|
| 667 | </code></pre> | 
|---|
| 668 | Note that if the serialization function is split between save and load, both | 
|---|
| 669 | functions must include the registration.  This is required to keep the save | 
|---|
| 670 | and corresponding load in syncronization. | 
|---|
| 671 | <p> | 
|---|
| 672 | This will work but may be inconvenient.  We don't always know which derived | 
|---|
| 673 | classes we are going to serialize when we write the code to serialize through | 
|---|
| 674 | a base class pointer.  Every time a new derived class is written we have to | 
|---|
| 675 | go back to all the places where the base class is serialized and update the | 
|---|
| 676 | code. | 
|---|
| 677 | <p> | 
|---|
| 678 | So we have another method: | 
|---|
| 679 | <pre><code> | 
|---|
| 680 | #include <boost/serialization/export.hpp> | 
|---|
| 681 | ... | 
|---|
| 682 | BOOST_CLASS_EXPORT_GUID(derived_one, "derived_one") | 
|---|
| 683 | BOOST_CLASS_EXPORT_GUID(derived_two, "derived_two") | 
|---|
| 684 |  | 
|---|
| 685 | main(){ | 
|---|
| 686 |     ... | 
|---|
| 687 |     base *b; | 
|---|
| 688 |     ... | 
|---|
| 689 |     ar & b;  | 
|---|
| 690 | } | 
|---|
| 691 | </code></pre> | 
|---|
| 692 | The macro <code style="white-space: normal">BOOST_CLASS_EXPORT_GUID</code> associates a string literal | 
|---|
| 693 | with a class. In the above example we've used a string rendering | 
|---|
| 694 | of the class name. If a object of such an "exported" class is serialized | 
|---|
| 695 | through a pointer and is otherwise unregistered, the "export" string is  | 
|---|
| 696 | included in the archive. When the archive  | 
|---|
| 697 | is later read, the string literal is used to find the class which  | 
|---|
| 698 | should be created by the serialization library. | 
|---|
| 699 | This permits each class to be in a separate header file along with its  | 
|---|
| 700 | string identifier. There is no need to maintain a separate "pre-registration"  | 
|---|
| 701 | of derived classes that might be serialized.  This method of | 
|---|
| 702 | registration is referred to as "key export".  More information on this | 
|---|
| 703 | topic is found in the section Class Traits -  | 
|---|
| 704 | <a target="detail" href="traits.html#export">Export Key</a>. | 
|---|
| 705 | <p> | 
|---|
| 706 | <h4><a name="instantiation">Instantiation</a></h4> | 
|---|
| 707 | Registration by means of any of the above methods fulfill another role  | 
|---|
| 708 | whose importance might not be obvious.  This system relies on templated | 
|---|
| 709 | functions of the form <code style="white-space: normal">template<class Archive, class T></code>. | 
|---|
| 710 | This means that serialization code must be instantiated for each | 
|---|
| 711 | combination of archive and data type that is serialized in the program. | 
|---|
| 712 | <p> | 
|---|
| 713 | Polymorphic pointers of derived classes may never be referred to  | 
|---|
| 714 | explictly by the program so normally code to serialize such classes | 
|---|
| 715 | would never be instantiated.  So in addition to including export key | 
|---|
| 716 | strings in an archive, <code style="white-space: normal">BOOST_CLASS_EXPORT_GUID</code> explicitly | 
|---|
| 717 | instantiates the class serialization code for all archive classes used  | 
|---|
| 718 | by the program.   | 
|---|
| 719 | <p> | 
|---|
| 720 | In order to do this,  | 
|---|
| 721 | <a href="../../../boost/serialization/export.hpp" target="export_hpp">export.hpp</a> | 
|---|
| 722 | includes meta programming code to build a <code style="white-space: normal">mpl::list</code>   | 
|---|
| 723 | of all the file types used by the module by checking for definition of the header  | 
|---|
| 724 | inclusion guards. | 
|---|
| 725 |  | 
|---|
| 726 | Using this list,   | 
|---|
| 727 | <code style="white-space: normal">BOOST_CLASS_EXPORT_GUID</code> will explicitly instantiate serialization | 
|---|
| 728 | code for all exported classes. | 
|---|
| 729 | For this implementaton to function, the header file  | 
|---|
| 730 | <a href="../../../boost/serialization/export.hpp" target="export_hpp">export.hpp</a> | 
|---|
| 731 | has to come after all the archive header files.  This is enforced | 
|---|
| 732 | by code at the end of the header file: | 
|---|
| 733 | <a href="../../../boost/archive/basic_archive.hpp" target="basic_archive_hpp">basic_archive.hpp</a> | 
|---|
| 734 | which will trip a STATIC_ASSERT if this requirement is violated. | 
|---|
| 735 |  | 
|---|
| 736 | <h4><a name="selectivetracking">Selective Tracking</a></h4> | 
|---|
| 737 | Whether or not an object is tracked is determined by its | 
|---|
| 738 | <a target="detail" href="traits.html#tracking">object tracking trait</a>. | 
|---|
| 739 | The default setting for user defined types is <code style="white-space: normal">track_selectively</code>. | 
|---|
| 740 | That is, track objects if and only if they are serialized through pointers anywhere | 
|---|
| 741 | in the program. Any  objects that are "registered" by any of the above means are presumed | 
|---|
| 742 | to be serialized through pointers somewhere in the program and therefore | 
|---|
| 743 | would be tracked. In certain situations this could lead to an inefficiency. | 
|---|
| 744 | Suppose we have a class module used by multiple programs.  Because | 
|---|
| 745 | some programs serializes polymorphic pointers to objects of this class, we  | 
|---|
| 746 | <a target="detail" href="traits.html#export">export</a> a class | 
|---|
| 747 | identifier by specifying <code style="white-space: normal">BOOST_CLASS_EXPORT</code> in the | 
|---|
| 748 | class header.  When this module is included by another program, | 
|---|
| 749 | objects of this class will always be tracked even though it | 
|---|
| 750 | may not be necessary.  This situation could be addressed by using  | 
|---|
| 751 | <a target="detail" href="traits.html#tracking"><code style="white-space: normal">track_never</code></a>   | 
|---|
| 752 | in those programs. | 
|---|
| 753 | <p> | 
|---|
| 754 | It could also occur that even though a program serializes through  | 
|---|
| 755 | a pointer, we are more concerned with efficiency than avoiding the | 
|---|
| 756 | the possibility of creating duplicate objects.  It could be | 
|---|
| 757 | that we happen to know that there will be no duplicates.  It could | 
|---|
| 758 | also be that the creation of a few duplicates is benign and not | 
|---|
| 759 | worth avoiding given the runtime cost of tracking duplicates. | 
|---|
| 760 | Again, <a target="detail" href="traits.html#tracking"><code style="white-space: normal">track_never</code></a>   | 
|---|
| 761 | can be used. | 
|---|
| 762 | <h4><a name="runtimecasting">Runtime Casting</a></h4> | 
|---|
| 763 | In order to properly translate between base and derived pointers | 
|---|
| 764 | at runtime, the system requires each base/derived pair be found | 
|---|
| 765 | in a table.  A side effect of serializing a base object with | 
|---|
| 766 | <code style="white-space: normal">boost::serialization::base_object<Base>(Derived &)</code> | 
|---|
| 767 | is to ensure that the base/derived pair is added to the table | 
|---|
| 768 | before the <code style="white-space: normal">main</code> function is entered. | 
|---|
| 769 | This is very convenient and results in a clean syntax.  The only | 
|---|
| 770 | problem is that it can occur where a derived class serialized | 
|---|
| 771 | through a pointer has no need to invoke the serialization of | 
|---|
| 772 | its base class.  In such a case, there are two choices.  The obvious | 
|---|
| 773 | one is to invoke the base class serialization with <code style="white-space: normal">base_object</code> | 
|---|
| 774 | and specify an empty function for the base class serialization. | 
|---|
| 775 | The alternative is to "register" the Base/Derived relationship | 
|---|
| 776 | explicitly by invoking the template  | 
|---|
| 777 | <code style="white-space: normal">void_cast_register<Derived, Base>();</code>. | 
|---|
| 778 | Note that this usage of the term "register" is not related | 
|---|
| 779 | to its usage in the previous section.  Here is an example of how this is done: | 
|---|
| 780 | <pre><code> | 
|---|
| 781 | #include <sstream> | 
|---|
| 782 | #include <boost/serialization/serialization.hpp> | 
|---|
| 783 | #include <boost/archive/text_iarchive.hpp> | 
|---|
| 784 | #include <boost/serialization/export.hpp> | 
|---|
| 785 |  | 
|---|
| 786 | class base { | 
|---|
| 787 |     friend class boost::serialization::access; | 
|---|
| 788 |     //... | 
|---|
| 789 |     // only required when using method 1 below | 
|---|
| 790 |     // no real serialization required - specify a vestigial one | 
|---|
| 791 |     template<class Archive> | 
|---|
| 792 |     void serialize(Archive & ar, const unsigned int file_version){} | 
|---|
| 793 | }; | 
|---|
| 794 |  | 
|---|
| 795 | class derived : public base { | 
|---|
| 796 |     friend class boost::serialization::access; | 
|---|
| 797 |     template<class Archive> | 
|---|
| 798 |     void serialize(Archive & ar, const unsigned int file_version){ | 
|---|
| 799 |         // method 1 : invoke base class serialization | 
|---|
| 800 |         boost::serialization::base_object<base>(*this); | 
|---|
| 801 |         // method 2 : explicitly register base/derived relationship | 
|---|
| 802 |         boost::serialization::void_cast_register<derived, base>(); | 
|---|
| 803 |     } | 
|---|
| 804 | }; | 
|---|
| 805 |  | 
|---|
| 806 | BOOST_CLASS_EXPORT_GUID(derived, "derived") | 
|---|
| 807 |  | 
|---|
| 808 | main(){ | 
|---|
| 809 |     //... | 
|---|
| 810 |     std::stringstream ss; | 
|---|
| 811 |     boost::archive::text_iarchive ar(ss); | 
|---|
| 812 |     base *b; | 
|---|
| 813 |     ar >> b;  | 
|---|
| 814 | } | 
|---|
| 815 | </code></pre> | 
|---|
| 816 | <p> | 
|---|
| 817 |  | 
|---|
| 818 | In order for this template to be invoked in code compiled by non-conforming | 
|---|
| 819 | compilers, the following syntax may be used: | 
|---|
| 820 | <pre><code> | 
|---|
| 821 | boost::serialization::void_cast_register( | 
|---|
| 822 |     static_cast<Derived *>(NULL), | 
|---|
| 823 |     static_cast<Base *>(NULL) | 
|---|
| 824 | ); | 
|---|
| 825 | </code></pre> | 
|---|
| 826 | For more information, see <a target="detail" href="implementation.html#tempatesyntax">Template Invocation syntax</a> | 
|---|
| 827 |  | 
|---|
| 828 | <h3><a name="references"></a>References</h3> | 
|---|
| 829 | Classes that contain reference members will generally require | 
|---|
| 830 | non-default constructors as references can only be set when | 
|---|
| 831 | an instance is constructed. The example of the previous section | 
|---|
| 832 | is slightly more complex if the class has reference members. | 
|---|
| 833 | This raises the question of how and where the objects being | 
|---|
| 834 | referred to are stored and how are they created. Also there is the question about | 
|---|
| 835 | references to polymorphic base classes.  Basically, these | 
|---|
| 836 | are the same questions that arise regarding pointers.  This is | 
|---|
| 837 | no surprise as references are really a special kind of pointer. | 
|---|
| 838 | We address these questions by serializing references as though | 
|---|
| 839 | they were pointers. | 
|---|
| 840 | <pre><code> | 
|---|
| 841 | class object; | 
|---|
| 842 | class my_class { | 
|---|
| 843 | private: | 
|---|
| 844 |     friend class boost::serialization::access; | 
|---|
| 845 |     int member1; | 
|---|
| 846 |     object & member2; | 
|---|
| 847 |     template<class Archive> | 
|---|
| 848 |     void serialize(Archive &ar, const unsigned int file_version); | 
|---|
| 849 | public: | 
|---|
| 850 |     my_class(int m, object & o) : | 
|---|
| 851 |         member1(m),  | 
|---|
| 852 |         member2(o) | 
|---|
| 853 |     {} | 
|---|
| 854 | }; | 
|---|
| 855 | </code></pre> | 
|---|
| 856 | the overrides would be: | 
|---|
| 857 | <pre><code> | 
|---|
| 858 | namespace boost { namespace serialization { | 
|---|
| 859 | template<class Archive> | 
|---|
| 860 | inline void save_construct_data( | 
|---|
| 861 |     Archive & ar, const my_class * t, const unsigned int file_version | 
|---|
| 862 | ){ | 
|---|
| 863 |     // save data required to construct instance | 
|---|
| 864 |     ar << t.member1; | 
|---|
| 865 |     // serialize reference to object as a pointer | 
|---|
| 866 |     ar << & t.member2; | 
|---|
| 867 | } | 
|---|
| 868 |  | 
|---|
| 869 | template<class Archive> | 
|---|
| 870 | inline void load_construct_data( | 
|---|
| 871 |     Archive & ar, my_class * t, const unsigned int file_version | 
|---|
| 872 | ){ | 
|---|
| 873 |     // retrieve data from archive required to construct new instance | 
|---|
| 874 |     int m; | 
|---|
| 875 |     ar >> m; | 
|---|
| 876 |     // create and load data through pointer to object | 
|---|
| 877 |     // tracking handles issues of duplicates. | 
|---|
| 878 |     object * optr; | 
|---|
| 879 |     ar >> optr; | 
|---|
| 880 |     // invoke inplace constructor to initialize instance of my_class | 
|---|
| 881 |     ::new(t)my_class(m, *optr); | 
|---|
| 882 | } | 
|---|
| 883 | }} // namespace ... | 
|---|
| 884 | </code></pre> | 
|---|
| 885 |  | 
|---|
| 886 | <h3><a name="arrays"></a>Arrays</h3> | 
|---|
| 887 | If <code style="white-space: normal">T</code> is a serializable type,  | 
|---|
| 888 | then any native C++ array of type T is a serializable type. | 
|---|
| 889 | That is, if <code style="white-space: normal">T</code> | 
|---|
| 890 | is a serializable type, then the following | 
|---|
| 891 | is automatically available and will function as expected: | 
|---|
| 892 | <pre><code> | 
|---|
| 893 | T t[4]; | 
|---|
| 894 | ar << t; | 
|---|
| 895 |     ... | 
|---|
| 896 | ar >> t; | 
|---|
| 897 | </code></pre> | 
|---|
| 898 |  | 
|---|
| 899 | <h2><a href="traits.html">Class Serialization Traits</a></h2> | 
|---|
| 900 |  | 
|---|
| 901 | <h2><a href="wrappers.html">Serialization Wrappers</a></h2> | 
|---|
| 902 |  | 
|---|
| 903 | <h2><a name="models"></a>Models - Serialization Implementations Included in the Library</h2> | 
|---|
| 904 | The facilities described above are sufficient to implement  | 
|---|
| 905 | serialization for all STL containers.  In fact, this has been done | 
|---|
| 906 | and has been included in the library.  For example, in order to use | 
|---|
| 907 | the included serialization code for <code style="white-space: normal">std::list</code>, use: | 
|---|
| 908 | <pre><code> | 
|---|
| 909 | #include <boost/serialization/list.hpp> | 
|---|
| 910 | </code></pre> | 
|---|
| 911 | rather than | 
|---|
| 912 | <pre><code> | 
|---|
| 913 | #include <list> | 
|---|
| 914 | </code></pre> | 
|---|
| 915 | Since the former includes the latter, this all that is necessary. | 
|---|
| 916 | The same holds true for all STL collections as well as templates | 
|---|
| 917 | required to support them (e.g. <code style="white-space: normal">std::pair</code>). | 
|---|
| 918 | <p> | 
|---|
| 919 | As of this writing, the library contains serialization of the following boost clases: | 
|---|
| 920 | <ul> | 
|---|
| 921 |   <li>optional | 
|---|
| 922 |   <li>variant | 
|---|
| 923 |   <li>scoped_ptr | 
|---|
| 924 |   <li>shared_ptr | 
|---|
| 925 |   <li>auto_ptr (demo) | 
|---|
| 926 | </ul> | 
|---|
| 927 | Others are being added to the list so check the boost files section and headers for | 
|---|
| 928 | new implmentations! | 
|---|
| 929 | <hr> | 
|---|
| 930 | <p><i>© Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 2002-2004.  | 
|---|
| 931 | Distributed under the Boost Software License, Version 1.0. (See | 
|---|
| 932 | accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | 
|---|
| 933 | </i></p> | 
|---|
| 934 | </body> | 
|---|
| 935 | </html> | 
|---|