Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/serialization/doc/serialization.html @ 20

Last change on this file since 20 was 12, checked in by landauf, 18 years ago

added boost

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