]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/serialization/doc/serialization.html
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / serialization / doc / serialization.html
CommitLineData
7c673cae
FG
1<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
2<html>
3<!--
4(C) Copyright 2002-4 Robert Ramey - http://www.rrsd.com .
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 &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 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">&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 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 &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 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&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>
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 &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
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">&lt;&lt;</code>
494and <code style="white-space: normal">&gt;&gt;</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&lt;class Archive, class T&gt;
520inline void load_construct_data(
521 Archive &amp; 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&lt;class Archive&gt;
542 void serialize(Archive &amp;ar, const unsigned int file_version){
543 ar &amp; 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&lt;class Archive&gt;
558inline void save_construct_data(
559 Archive &amp; ar, const my_class * t, const unsigned int file_version
560){
561 // save data required to construct instance
562 ar &lt;&lt; t-&gt;m_attribute;
563}
564
565template&lt;class Archive&gt;
566inline void load_construct_data(
567 Archive &amp; 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 &gt;&gt; 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 &amp; 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 &amp; d1;
638 ar &amp; 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 &amp; 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&lt;class T&gt;
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&lt;derived_one&gt;();
669 ar.template register_type&lt;derived_two&gt;();
670 base *b;
671 ...
672 ar &amp; 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 &lt;boost/serialization/export.hpp&gt;
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 &amp; 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&lt;class Archive, class T&gt;</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&lt;Base&gt;(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&lt;Derived, Base&gt;();</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 &lt;sstream&gt;
774#include &lt;boost/serialization/serialization.hpp&gt;
775#include &lt;boost/archive/text_iarchive.hpp&gt;
776#include &lt;boost/serialization/export.hpp&gt;
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&lt;class Archive&gt;
784 void serialize(Archive &amp; ar, const unsigned int file_version){}
785};
786
787class derived : public base {
788 friend class boost::serialization::access;
789 template&lt;class Archive&gt;
790 void serialize(Archive &amp; ar, const unsigned int file_version){
791 // method 1 : invoke base class serialization
792 ar & boost::serialization::base_object&lt;base&gt;(*this);
793 // method 2 : explicitly register base/derived relationship
794 boost::serialization::void_cast_register&lt;derived, base&gt;(
795 static_cast&lt;derived *&gt;(NULL),
796 static_cast&lt;base *&gt;(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 &gt;&gt; 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&lt;Derived *&gt;(NULL),
818 static_cast&lt;Base *&gt;(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 &amp; member2;
842 template&lt;class Archive&gt;
843 void serialize(Archive &amp;ar, const unsigned int file_version);
844public:
845 my_class(int m, object &amp; o) :
846 member1(m),
847 member2(o)
848 {}
849};
850</code></pre>
851the overrides would be:
852<pre><code>
853namespace boost { namespace serialization {
854template&lt;class Archive&gt;
855inline void save_construct_data(
856 Archive &amp; ar, const my_class * t, const unsigned int file_version
857){
858 // save data required to construct instance
859 ar &lt;&lt; t.member1;
860 // serialize reference to object as a pointer
861 ar &lt;&lt; &amp; t.member2;
862}
863
864template&lt;class Archive&gt;
865inline void load_construct_data(
866 Archive &amp; 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 &gt;&gt; m;
871 // create and load data through pointer to object
872 // tracking handles issues of duplicates.
873 object * optr;
874 ar &gt;&gt; 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 &lt;&lt; t;
890 ...
891ar &gt;&gt; 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 &lt;boost/serialization/list.hpp&gt;
905</code></pre>
906rather than
907<pre><code>
908#include &lt;list&gt;
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>&copy; 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>