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