Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/serialization/doc/serialization.html @ 33

Last change on this file since 33 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 39.7 KB
Line 
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="#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
69A type <code style="white-space: normal">T</code> is <strong>Serializable</strong> 
70if 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>
91The template operators &amp;, &lt;&lt;, and &gt;&gt; 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 &amp;, &lt;&lt;, and &gt;&gt;
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&lt;class Archive, class T&gt;
113inline void serialize(
114    Archive &amp; ar,
115    T &amp; 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&lt;class Archive&gt;
127void serialize(Archive &amp;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 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">&amp;</code> operator is
146defined as <code style="white-space: normal">&lt;&lt;</code>
147for output archives and as <code style="white-space: normal">&gt;&gt;</code> input archives.  The
148"polymorphic" behavior of the <code style="white-space: normal">&amp;</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&lt;class Archive&gt;
165inline void serialize(
166    Archive &amp; ar,
167    my_class &amp; 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 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>
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 &amp;</code> to all the data members of the class.
206<pre><code>
207{
208    // save/load class member variables
209    ar &amp; member1;
210    ar &amp; 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&lt;class Base, class Derived&gt;
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 &amp; boost::serialization::base_object&lt;base_class_of_T&gt;(*this);
233    // save/load class member variables
234    ar &amp; member1;
235    ar &amp; 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 &amp; const_cast&lt;T &amp;&gt;(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 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&lt;T&gt;</code> and for
271<code style="white-space: normal">std::list&lt;T&gt;</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&lt; boost::shared_ptr&lt; my_t&gt; &gt;</code> is already available
274for use.
275<p>
276See for 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 &amp; boost::serialization::base_object&lt;base_class_of_T&gt;(*this);
324    // save/load class member variables
325    ar &amp; member1;
326    ar &amp; member2;
327    // if its a recent version of the class
328    if(1 &lt; file_version)
329        // save load recently added class members
330        ar &amp; 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&lt;class Archive&gt;
345void save(Archive &amp; ar, const unsigned int version) const
346{
347    // invoke serialization of the base class
348    ar &lt;&lt; boost::serialization::base_object&lt;const base_class_of_T&gt;(*this);
349    ar &lt;&lt; member1;
350    ar &lt;&lt; member2;
351    ar &lt;&lt; member3;
352}
353
354template&lt;class Archive&gt;
355void load(Archive &amp; ar, const unsigned int version)
356{
357    // invoke serialization of the base class
358    ar &gt;&gt; boost::serialization::base_object&lt;base_class_of_T&gt;(*this);
359    ar &gt;&gt; member1;
360    ar &gt;&gt; member2;
361    if(version &gt; 0)
362        ar &gt;&gt; member3;
363}
364
365template&lt;class Archive&gt;
366void serialize(
367    Archive &amp; 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&lt;class Archive&gt;
395void save(Archive &amp; ar, const my_class &amp; t, unsigned int version)
396{
397    ...
398}
399template&lt;class Archive&gt;
400void load(Archive &amp; ar, my_class &amp; 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&lt;class Archive&gt;
414inline void serialize(
415    Archive &amp; ar,
416    my_class &amp; 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">&amp;</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">&amp;</code> 
435operator and <code style="white-space: normal">serialize</code>
436function guarantees that this is always the case and will minimize the
437occurence 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
441<h2><a name="pointeroperators">Pointers</a></h2>
442A pointer to any class instance can be serialized with any of the archive
443save/load operators.
444<p>
445To properly save and restore an object through a pointer the
446following 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
467This serialization library addresses all of the above
468considerations. The process of saving and loading an object
469through a pointer is non-trivial. It can be summarized as
470follows:
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>
478Loading 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
488Given that class instances are saved/loaded to/from the archive
489only once, regardless of how many times they are serialized with
490the <code style="white-space: normal">&lt;&lt;</code> 
491and <code style="white-space: normal">&gt;&gt;</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>
499Serialization of pointers of derived types through a pointer to the
500base class may require a little extra "help".  Also, the programmer
501may desire to modify the process described above for his own reasons.
502For example, it might be desired to suppress the tracking of objects
503as it is known a priori that the application in question can never
504create duplicate objects.  Serialization of pointers can be "fine tuned"
505via the specification of <a target="detail" href="traits.html#Traits">Class Serialization Traits</a>
506as described in
507<a target="detail" href="special.html#derivedpointers">
508another section of this manual
509</a>
510
511<h3><a name="constructors">Non-Default Constructors</a></h3>
512Serialization of pointers is implemented in the library with code
513similar to the following:
514<pre><code>
515// load data required for construction and invoke constructor in place
516template&lt;class Archive, class T&gt;
517inline void load_construct_data(
518    Archive &amp; 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>
525The default <code style="white-space: normal">load_construct_data</code> invokes the
526default constructor "in-place" to initialize the memory.
527<p>
528If there is no such default constructor, the function templates
529<code style="white-space: normal">load_construct_data</code> and
530perhaps <code style="white-space: normal">save_construct_data</code>
531will have to be overridden.  Here is a simple example:
532<pre><code>
533class my_class {
534private:
535    friend class boost::serialization::access;
536    int member;
537    template&lt;class Archive&gt;
538    void serialize(Archive &amp;ar, const unsigned int file_version){
539        ar &amp; member;
540    }
541public:
542    my_class(int m) :
543        member(m)
544    {}
545};
546</code></pre>
547the overrides would be:
548<pre><code>
549namespace boost { namespace serialization {
550template&lt;class Archive&gt;
551inline void save_construct_data(
552    Archive &amp; ar, const my_class * t, const unsigned int file_version
553){
554    // save data required to construct instance
555    ar &lt;&lt; t-&gt;member;
556}
557
558template&lt;class Archive&gt;
559inline void load_construct_data(
560    Archive &amp; 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 &gt;&gt; m;
565    // invoke inplace constructor to initialize instance of my_class
566    ::new(t)my_class(m);
567}
568}} // namespace ...
569</code></pre>
570In addition to the deserialization of pointers, these overrides are used
571in the deserialization of STL containers whose element type has no default
572constructor.
573
574<h3><a name="derivedpointers">Pointers to Objects of Derived Classes</a></h3>
575<h4><a name="registration">Registration</a></h4>
576Consider the following:
577<pre><code>
578class base {
579    ...
580};
581class derived_one : public base {
582    ...
583};
584class derived_two : public base {
585    ...
586};
587main(){
588    ...
589    base *b;
590    ...
591    ar &amp; b;
592}
593</code></pre>
594When saving <code style="white-space: normal">b</code> what kind of object should be saved?
595When loading <code style="white-space: normal">b</code> what kind of object should be created?
596Should 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>
599It 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.
601If <code style="white-space: normal">base</code> is not polymorphic, that is if it has no
602virtual functions, then an object of the type <code style="white-space: normal">base</code>
603will 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
607If the base class is polymorphic, an object of the most derived type
608(<code style="white-space: normal">derived_one</code>
609or <code style="white-space: normal">derived_two</code>
610in this case) will be serialized.  The question of which type of object is to be
611serialized is (almost) automatically handled by the library.
612<p>
613The system "registers" each class in an archive the first time an object of that
614class it is serialized and assigns a sequential number to it.  Next time an
615object of that class is serialized in that same archive, this number is written
616in the archive.  So every class is identified uniquely within the archive. 
617When the archive is read back in, each new sequence number is re-associated with
618the class being read.  Note that this implies that "registration" has to occur
619during both save and load so that the class-integer table built on load
620is identical to the class-integer table built on save. In fact, the key to
621whole serialization system is that things are always saved and loaded in
622the same sequence.  This includes "registration".
623<p>
624Expanding our previous example:
625<pre><code>
626main(){
627    derived_one d1;
628    derived_two d2:
629    ...
630    ar &amp; d1;
631    ar &amp; 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 &amp; b;
639}
640</code></pre>
641When <code style="white-space: normal">b</code> is read it is
642preceded by a unique (to the archive) class identifier which
643has 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>
646If a derived class has NOT been automatically "registered" as described
647above, an <a target="detail" href="exceptions.html#unregistered_class">
648<code style="white-space: normal">unregistered_class</code></a> exception
649will be thrown when serialization is invoked.
650<p>
651This can be addressed by registering the derived class explicitly.  All archives are
652derived from a base class which implements the following template:
653<pre><code>
654template&lt;class T&gt;
655register_type();
656</code></pre>
657So our problem could just as well be addressed by writing:
658<pre><code>
659main(){
660    ...
661    ar.template register_type&lt;derived_one&gt;();
662    ar.template register_type&lt;derived_two&gt;();
663    base *b;
664    ...
665    ar &amp; b;
666}
667</code></pre>
668Note that if the serialization function is split between save and load, both
669functions must include the registration.  This is required to keep the save
670and corresponding load in syncronization.
671<p>
672This will work but may be inconvenient.  We don't always know which derived
673classes we are going to serialize when we write the code to serialize through
674a base class pointer.  Every time a new derived class is written we have to
675go back to all the places where the base class is serialized and update the
676code.
677<p>
678So we have another method:
679<pre><code>
680#include &lt;boost/serialization/export.hpp&gt;
681...
682BOOST_CLASS_EXPORT_GUID(derived_one, "derived_one")
683BOOST_CLASS_EXPORT_GUID(derived_two, "derived_two")
684
685main(){
686    ...
687    base *b;
688    ...
689    ar &amp; b;
690}
691</code></pre>
692The macro <code style="white-space: normal">BOOST_CLASS_EXPORT_GUID</code> associates a string literal
693with a class. In the above example we've used a string rendering
694of the class name. If a object of such an "exported" class is serialized
695through a pointer and is otherwise unregistered, the "export" string is
696included in the archive. When the archive
697is later read, the string literal is used to find the class which
698should be created by the serialization library.
699This permits each class to be in a separate header file along with its
700string identifier. There is no need to maintain a separate "pre-registration"
701of derived classes that might be serialized.  This method of
702registration is referred to as "key export".  More information on this
703topic 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>
707Registration by means of any of the above methods fulfill another role
708whose importance might not be obvious.  This system relies on templated
709functions of the form <code style="white-space: normal">template&lt;class Archive, class T&gt;</code>.
710This means that serialization code must be instantiated for each
711combination of archive and data type that is serialized in the program.
712<p>
713Polymorphic pointers of derived classes may never be referred to
714explictly by the program so normally code to serialize such classes
715would never be instantiated.  So in addition to including export key
716strings in an archive, <code style="white-space: normal">BOOST_CLASS_EXPORT_GUID</code> explicitly
717instantiates the class serialization code for all archive classes used
718by the program. 
719<p>
720In order to do this,
721<a href="../../../boost/serialization/export.hpp" target="export_hpp">export.hpp</a>
722includes meta programming code to build a <code style="white-space: normal">mpl::list</code> 
723of all the file types used by the module by checking for definition of the header
724inclusion guards.
725
726Using this list, 
727<code style="white-space: normal">BOOST_CLASS_EXPORT_GUID</code> will explicitly instantiate serialization
728code for all exported classes.
729For this implementaton to function, the header file
730<a href="../../../boost/serialization/export.hpp" target="export_hpp">export.hpp</a>
731has to come after all the archive header files.  This is enforced
732by code at the end of the header file:
733<a href="../../../boost/archive/basic_archive.hpp" target="basic_archive_hpp">basic_archive.hpp</a>
734which will trip a STATIC_ASSERT if this requirement is violated.
735
736<h4><a name="selectivetracking">Selective Tracking</a></h4>
737Whether or not an object is tracked is determined by its
738<a target="detail" href="traits.html#tracking">object tracking trait</a>.
739The default setting for user defined types is <code style="white-space: normal">track_selectively</code>.
740That is, track objects if and only if they are serialized through pointers anywhere
741in the program. Any  objects that are "registered" by any of the above means are presumed
742to be serialized through pointers somewhere in the program and therefore
743would be tracked. In certain situations this could lead to an inefficiency.
744Suppose we have a class module used by multiple programs.  Because
745some programs serializes polymorphic pointers to objects of this class, we
746<a target="detail" href="traits.html#export">export</a> a class
747identifier by specifying <code style="white-space: normal">BOOST_CLASS_EXPORT</code> in the
748class header.  When this module is included by another program,
749objects of this class will always be tracked even though it
750may 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> 
752in those programs.
753<p>
754It could also occur that even though a program serializes through
755a pointer, we are more concerned with efficiency than avoiding the
756the possibility of creating duplicate objects.  It could be
757that we happen to know that there will be no duplicates.  It could
758also be that the creation of a few duplicates is benign and not
759worth avoiding given the runtime cost of tracking duplicates.
760Again, <a target="detail" href="traits.html#tracking"><code style="white-space: normal">track_never</code></a> 
761can be used.
762<h4><a name="runtimecasting">Runtime Casting</a></h4>
763In order to properly translate between base and derived pointers
764at runtime, the system requires each base/derived pair be found
765in a table.  A side effect of serializing a base object with
766<code style="white-space: normal">boost::serialization::base_object&lt;Base&gt;(Derived &)</code>
767is to ensure that the base/derived pair is added to the table
768before the <code style="white-space: normal">main</code> function is entered.
769This is very convenient and results in a clean syntax.  The only
770problem is that it can occur where a derived class serialized
771through a pointer has no need to invoke the serialization of
772its base class.  In such a case, there are two choices.  The obvious
773one is to invoke the base class serialization with <code style="white-space: normal">base_object</code>
774and specify an empty function for the base class serialization.
775The alternative is to "register" the Base/Derived relationship
776explicitly by invoking the template
777<code style="white-space: normal">void_cast_register&lt;Derived, Base&gt;();</code>.
778Note that this usage of the term "register" is not related
779to its usage in the previous section.  Here is an example of how this is done:
780<pre><code>
781#include &lt;sstream&gt;
782#include &lt;boost/serialization/serialization.hpp&gt;
783#include &lt;boost/archive/text_iarchive.hpp&gt;
784#include &lt;boost/serialization/export.hpp&gt;
785
786class 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&lt;class Archive&gt;
792    void serialize(Archive &amp; ar, const unsigned int file_version){}
793};
794
795class derived : public base {
796    friend class boost::serialization::access;
797    template&lt;class Archive&gt;
798    void serialize(Archive &amp; ar, const unsigned int file_version){
799        // method 1 : invoke base class serialization
800        boost::serialization::base_object&lt;base&gt;(*this);
801        // method 2 : explicitly register base/derived relationship
802        boost::serialization::void_cast_register&lt;derived, base&gt;();
803    }
804};
805
806BOOST_CLASS_EXPORT_GUID(derived, "derived")
807
808main(){
809    //...
810    std::stringstream ss;
811    boost::archive::text_iarchive ar(ss);
812    base *b;
813    ar &gt;&gt; b;
814}
815</code></pre>
816<p>
817
818In order for this template to be invoked in code compiled by non-conforming
819compilers, the following syntax may be used:
820<pre><code>
821boost::serialization::void_cast_register(
822    static_cast&lt;Derived *&gt;(NULL),
823    static_cast&lt;Base *&gt;(NULL)
824);
825</code></pre>
826For more information, see <a target="detail" href="implementation.html#tempatesyntax">Template Invocation syntax</a>
827
828<h3><a name="references"></a>References</h3>
829Classes that contain reference members will generally require
830non-default constructors as references can only be set when
831an instance is constructed. The example of the previous section
832is slightly more complex if the class has reference members.
833This raises the question of how and where the objects being
834referred to are stored and how are they created. Also there is the question about
835references to polymorphic base classes.  Basically, these
836are the same questions that arise regarding pointers.  This is
837no surprise as references are really a special kind of pointer.
838We address these questions by serializing references as though
839they were pointers.
840<pre><code>
841class object;
842class my_class {
843private:
844    friend class boost::serialization::access;
845    int member1;
846    object &amp; member2;
847    template&lt;class Archive&gt;
848    void serialize(Archive &amp;ar, const unsigned int file_version);
849public:
850    my_class(int m, object &amp; o) :
851        member1(m),
852        member2(o)
853    {}
854};
855</code></pre>
856the overrides would be:
857<pre><code>
858namespace boost { namespace serialization {
859template&lt;class Archive&gt;
860inline void save_construct_data(
861    Archive &amp; ar, const my_class * t, const unsigned int file_version
862){
863    // save data required to construct instance
864    ar &lt;&lt; t.member1;
865    // serialize reference to object as a pointer
866    ar &lt;&lt; &amp; t.member2;
867}
868
869template&lt;class Archive&gt;
870inline void load_construct_data(
871    Archive &amp; 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 &gt;&gt; m;
876    // create and load data through pointer to object
877    // tracking handles issues of duplicates.
878    object * optr;
879    ar &gt;&gt; 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>
887If <code style="white-space: normal">T</code> is a serializable type,
888then any native C++ array of type T is a serializable type.
889That is, if <code style="white-space: normal">T</code>
890is a serializable type, then the following
891is automatically available and will function as expected:
892<pre><code>
893T t[4];
894ar &lt;&lt; t;
895    ...
896ar &gt;&gt; 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>
904The facilities described above are sufficient to implement
905serialization for all STL containers.  In fact, this has been done
906and has been included in the library.  For example, in order to use
907the included serialization code for <code style="white-space: normal">std::list</code>, use:
908<pre><code>
909#include &lt;boost/serialization/list.hpp&gt;
910</code></pre>
911rather than
912<pre><code>
913#include &lt;list&gt;
914</code></pre>
915Since the former includes the latter, this all that is necessary.
916The same holds true for all STL collections as well as templates
917required to support them (e.g. <code style="white-space: normal">std::pair</code>).
918<p>
919As 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>
927Others are being added to the list so check the boost files section and headers for
928new implmentations!
929<hr>
930<p><i>&copy; Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 2002-2004.
931Distributed under the Boost Software License, Version 1.0. (See
932accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
933</i></p>
934</body>
935</html>
Note: See TracBrowser for help on using the repository browser.