Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/serialization/doc/traits.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: 19.2 KB
RevLine 
[29]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 - Class Serialization Traits</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">Class Serialization Traits</h2>
24    </td>
25  </tr>
26</table>
27<hr>
28<dl class="page-index">
29  <dt><a href="#version">Version</a>
30  <dt><a href="#level">Implementation Level</a>
31  <dt><a href="#tracking">Object Tracking</a>
32  <dt><a href="#export">Export Key</a>
33  <dt><a href="#abstract">Abstract</a>
34  <dt><a href="#typeinfo">Type Information Implementation</a>
35  <dt><a href="#templates">Template Serialization Traits</a>
36</dl>
37Serialization of data depends on the type of the data.  For example, for
38primitive types such as an <code style="white-space: normal">int</code>, it wouldn't make sense to save
39a version number in the archive. Likewise, for a data type that is never
40serialized through a pointer, it would (almost) never make sense to track
41the address of objects saved to/loaded from the archive as it will never
42be saved/loaded more than once in any case.  Details of
43serialization for a particular data type will vary depending on the
44type, the way it is used and specifications of the programmer.
45<p>
46One can alter the manner in which a particular data type is serialized
47by specifying one or more <strong>class serialization traits</strong>.
48It is not generally necessary for the programmer to explictly assign
49traits to his classes as there are default values for all traits.
50If the default values are not appropriate they can be assigned by the programmer.
51A template is used to associate a typename with a constant.  For example
52see <a href="../../../boost/serialization/version.hpp" target="version_hpp">
53version.hpp</a>
54<h3><a name="version">Version</a></h3>
55This header file includes the following code:
56
57<pre><code>
58namespace boost {
59namespace serialization {
60template&lt;class T&gt;
61struct version
62{
63    BOOST_STATIC_CONSTANT(unsigned int, value = 0);
64};
65} // namespace serialization
66} // namespace boost
67</code></pre>
68
69For any class <code style="white-space: normal">T</code>, The default definition
70of <code style="white-space: normal">boost::serialization::version&lt;T&gt;::value</code> is 0.
71If we want to assign a value of 2 as the version for class <code style="white-space: normal">my_class</code>
72we specialize the version template:
73<pre><code>
74namespace boost {
75namespace serialization {
76struct version&lt;my_class&gt;
77{
78    BOOST_STATIC_CONSTANT(unsigned int, value = 2);
79};
80} // namespace serialization
81} // namespace boost
82</code></pre>
83Now whenever the version number for class <code style="white-space: normal">my_class</code> is required,
84the value 2 will be returned rather than the default value of 0.
85<p>
86To diminish typing and enhance readability, a macro is defined
87so that instead of the above, we could write:
88<pre><code>
89BOOST_CLASS_VERSION(my_class, 2)
90</code></pre>
91which expands to the code above.
92
93<h3><a name="level">Implementation Level</a></h3>
94In the same manner as the above, the "level" of implementation of serialization is
95specified.  The header file <a href="../../../boost/serialization/level.hpp" 
96target="level_hpp">level.hpp</a> defines the following.
97<pre><code>
98// names for each level
99enum level_type
100{
101    // Don't serialize this type. An attempt to do so should
102    // invoke a compile time assertion.
103    not_serializable = 0,
104    // write/read this type directly to the archive. In this case
105    // serialization code won't be called.  This is the default
106    // case for fundamental types.  It presumes a member function or
107    // template in the archive class that can handle this type.
108    // there is no runtime overhead associated reading/writing
109    // instances of this level
110    primitive_type = 1,
111    // Serialize the objects of this type using the objects "serialize"
112    // function or template. This permits values to be written/read
113    // to/from archives but includes no class or version information.
114    object_serializable = 2,
115    ///////////////////////////////////////////////////////////////////
116    // once an object is serialized at one of the above levels, the
117    // corresponding archives cannot be read if the implementation level
118    // for the archive object is changed. 
119    ///////////////////////////////////////////////////////////////////
120    // Add class information to the archive.  Class information includes
121    // implementation level, class version and class name if available.
122    object_class_info = 3,
123};
124</code></pre>
125Using a macro defined in <code style="white-space: normal">level.hpp</code> we can specify
126that <code style="white-space: normal">my_class</code> should be serialized along with its version number:
127<pre><code>
128BOOST_CLASS_IMPLEMENTATION(my_class, boost::serialization::object_class_info)
129</code></pre>
130If implementation level is not explicitly assigned, the system uses
131a default according to the following rules.
132<ul>
133  <li>if the data type is <code style="white-space: normal">volatile</code> 
134assign <code style="white-space: normal">not_serializable</code>
135  <li>else if it's an enum or fundamental type assign <code style="white-space: normal">primitive_type</code>
136  <li>else assign <code style="white-space: normal">object_class_info</code>
137</ul>
138That is, for most user defined types, objects will be serialized along with
139class version information. This will permit one to maintain backward
140compatibility with archives which contain previous versions.  However, with this
141ability comes a small runtime cost.  For types whose definition will "never"
142change, efficiency can be gained by specifying <code style="white-space: normal">object_serializable</code> 
143to override the default setting of <code style="white-space: normal">object_class_info</code>
144For example,
145this has been done for the 
146<a href="../../../boost/serialization/binary_object.hpp" target="binary_object_hpp">
147binary_object wrapper</a>
148
149<h3><a name="tracking">Object Tracking</a></h3>
150Depending on the way a type is used, it may be necessary or convenient to
151track the address of objects saved and loaded.  For example, this is generally
152necessary while serializing objects through a pointer in order to be sure
153that multiple identical objects are not created when an archive is loaded.
154This "tracking behavior" is controlled by the type trait defined in the header
155file <a href="../../../boost/serialization/tracking.hpp" target="tracking_hpp">tracking.hpp</a>
156which defines the following:
157<pre><code>
158// names for each tracking level
159enum tracking_type
160{
161    // never track this type
162    track_never = 0,
163    // track objects of this type if the object is serialized through a
164    // pointer.
165    track_selectively = 1,
166    // always track this type
167    track_always = 2
168};
169</code></pre>
170A corresponding macro is defined so that we can use:
171<pre><code>
172BOOST_CLASS_TRACKING(my_class, boost::serialization::track_never)
173</code></pre>
174Default tracking traits are:
175<ul>
176  <li>For primitive, <code style="white-space: normal">track_never</code>.
177  <li>For pointers, <code style="white-space: normal">track_never</code>.
178  That is, addresses of addresses are not tracked by default.
179  <li>All current serialization wrappers such as <code style="white-space: normal">boost::serialization::nvp</code>,
180  <code style="white-space: normal">track_never</code>.
181  <li>For all other types, <code style="white-space: normal">track_selectivly</code>.
182  That is addresses of serialized objects are tracked if and only if
183  one or more of the following is true:
184  <ul>
185  <li>an object of this type is anywhere in the program serialized
186  through a pointer.
187  <li>the class is explicitly "exported" - see below.
188  <li>the class is explicitly "registered" in the archive
189  </ul>
190</ul>
191
192<p>
193The default behavior is almost always the most convenient one.  However,
194there a few cases where it would be desirable to override the
195default.  One case is that of a virtual base class. In a diamond
196heritance structure with a virtual base class, object tracking
197will prevent redundant save/load invocations.  So here is one
198case where it might be convenient to override the default tracking
199trait. <i>(Note: in a future version the default will be reimplemented
200to automatically track classes used as virtual bases).</i> This
201situation is demonstrated by
202<a href="../test/test_diamond.cpp" target="test_diamond_cpp">test_diamond.cpp</a>
203included with the library.
204<h3><a name="export">Export Key</a></h3>
205When serializing a derived class through a base class pointer, it
206may be convenient to define an external name by which the
207derived class can be identified. 
208<i>(<a target="detail" href="special.html#derivedpointers">Elsewhere</a>
209in this manual, the
210serialization of derived classes is addressed in detail.)</i>
211Standard C++ does implement <code style="white-space: normal">typeid()</code> which can be
212used to return a unique string for the class.  This is not entirely
213statisfactory for our purposes for the following reasons:
214<ul>
215  <li>There is no guarantee that the string is the same across platforms.
216  This would then fail to support portable archives.
217  <li>In using code modules from various sources, classes may have
218  to be wrapped in different namespaces in different programs.
219  <li>There might be classes locally defined in different code modules
220  that have the same name.
221  <li>There might be classes with different names that we want to
222  consider equivalent for purposes of of serialization.
223</ul>
224So the header file
225<a href="../../../boost/serialization/export.hpp" target="export_hpp">export.hpp</a>
226includes macro definitions to specify the external string used
227to identify the class.
228<i>(<b>GUID</b> stands for <b>G</b>lobally <b>U</b>nique <b>ID</b>entfier.)</i>
229<pre><code>
230BOOST_CLASS_EXPORT_GUID(my_class, "my_class_external_identifier")
231</code></pre>
232In a large majority of applications, the class name works just fine
233for the external identifier string so the following short cut is
234defined
235<pre><code>
236BOOST_CLASS_EXPORT(my_class)
237</code></pre>
238which expands to:
239<pre><code>
240BOOST_CLASS_EXPORT_GUID(my_class, "my_class")
241</code></pre>
242If the an external name is required somewhere in the program and none
243has been assigned, a static assertion will be invoked.
244<h3><a name="abstract">Abstract</a></h3>
245When serializing an object through a pointer to its base class
246and that base class is abstract (i.e. has at least one virtual function
247assigned a value of 0), A compile error will be emitted.  This is
248addressable in one over several ways:
249<ul>
250  <li>remove the =0 in the base classes so that the base class is no
251  longer abstract.
252  <li>implement is_abstract for your compiler. (code written according to
253  the C++ standard is included with this library.  But it is known to fail
254  on several compilers.
255  <li>use the macro <code style="white-space: normal">BOOST_IS_ABSTRACT(my_class)</code> to indicate
256  that the class is an abstract base class.  This will cause the compiler
257  to avoid generating code that causes this error.
258</ul>
259<h3><a name="typeinfo">Type Information Implementation</a></h3>
260This last trait is also related to the serialization of objects
261through a base class pointer.  The implementation of this facility
262requires the ability to determine at run time the true type of the
263object that a base class pointer points to.  Different serialization
264systems do this in different ways.  In our system, the default method
265is to use the function <code style="white-space: normal">typeid(...)</code> which is available
266in systems which support <b>RTTI</b> (<b>R</b>un <b>T</b>ime
267<b>T</b>ype <b>I</b>nformation).
268This will be satisfactory in almost all cases and most users of this
269library will lose nothing in skipping this section of the manual.
270<p>
271However, there are some cases where the default type determination
272system is not convenient.  Some platforms might not support
273RTTI or it may have been disabled in order to speed execution
274or for some other reason.  Some applications, E.G. runtime linking
275of plug-in modules, can't depend on C++ RTTI to determine the
276true derived class.  RTTI only returns the correct type for polymorphic
277classes - classes with at least one virtual function.  If any of these
278situations applies, one may substitute his own implementation of
279<code style="white-space: normal">extended_type_info</code>
280<p>
281The interface to facilities required to implement serialization is defined in
282<a href="../../../boost/serialization/extended_type_info.hpp" 
283target="extended_type_info_hpp">extended_type_info.hpp</a>.
284
285Default implementation of these facilities based on <code style="white-space: normal">typeid(...)</code>
286is defined in
287
288<a href="../../../boost/serialization/extended_type_info_typeid.hpp" 
289target="extended_type_info_typeid_hpp">extended_type_info_typeid.hpp</a>.
290
291An alternative implementation based on exported class identifiers
292is defined in
293<a href="../../../boost/serialization/extended_type_info_no_rtti.hpp" 
294target="extended_type_info_rtti_hpp">extended_type_info_no_rtti.hpp</a>.
295<p>
296By invoking the macro:
297<pre><code>
298BOOST_CLASS_TYPE_INFO(
299    my_class,
300    extended_type_info_no_rtti&lt;my_class&gt;
301)
302</code></pre>
303we can assign the type information implementation to each class on a case by
304case basis.  There is no requirement that all classes in a program use the same
305implementation of <code style="white-space: normal">extended_type_info</code>.  This supports the concept
306that serialization of each class is specified "once and for all" in a header
307file that can be included in any project without change.
308<p>
309This is illustrated by the test program
310<a href="../test/test_no_rtti.cpp" target="test_no_rtti_cpp">test_no_rtti.cpp</a>.
311Other implementations are possible and might be necessary for
312certain special cases.
313
314<h3><a name="templates">Template Serialization Traits</a></h3>
315In some instances it might be convenient to assign serialization traits
316to a whole group of classes at once.  Consider, the name-value pair
317wrapper
318<pre><code>
319template&lt;class T&gt;
320struct nvp : public std::pair&lt;const char *, T *&gt;
321{
322    ...
323};
324</code></pre>
325used by XML archives to associate a name with a data variable of type T.
326These data types are never tracked and never versioned.  So one might
327want to specify:
328<pre><code>
329BOOST_CLASS_IMPLEMENTATION(nvp&lt;T&gt;, boost::serialization::level_type::object_serializable)
330BOOST_CLASS_TRACKING(nvp&lt;T&gt;, boost::serialization::track_never)
331</code></pre>
332Examination of the definition of these macros reveals that they won't expand
333to sensible code when used with a template argument.  So rather than using the
334convenience macros, use the original definitions
335<pre><code>
336template&lt;class T&gt;
337struct implementation_level&lt;nvp&lt;T&gt; &gt;
338{
339    typedef mpl::integral_c_tag tag;
340    typedef mpl::int_&lt;object_serializable&gt; type;
341    BOOST_STATIC_CONSTANT(
342        int,
343        value = implementation_level::type::value
344    );
345};
346
347// nvp objects are generally created on the stack and are never tracked
348template&lt;class T&gt;
349struct tracking_level&lt;nvp&lt;T&gt; &gt;
350{
351    typedef mpl::integral_c_tag tag;
352    typedef mpl::int_&lt;track_never&gt; type;
353    BOOST_STATIC_CONSTANT(
354        int,
355        value = tracking_level::type::value
356    );
357};
358</code></pre>
359to assign serialization traits to all classes generated by the template
360<code style="white-space: normal">nvp&lt;T&gt;</code>
361<p>
362
363Note that it is only possible to use the above method to assign traits to
364templates when using compilers which correctly support Partial Template Specialization.
365
366One's first impulse might be to do something like:
367
368<pre><code>
369#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
370template&lt;class T&gt;
371struct implementation_level&lt;nvp&lt;T&gt; &gt;
372{
373   ... // see above
374};
375
376// nvp objects are generally created on the stack and are never tracked
377template&lt;class T&gt;
378struct tracking_level&lt;nvp&lt;T&gt; &gt;
379{
380   ... // see above
381};
382#endif
383</code></pre>
384This can be problematic when one wants to make his code <strong>and archives</strong>
385portable to other platforms.  It means the she objects will be serialized differently
386depending on the platform used.  This implies that objects saved from one platform
387won't be loaded properly on another.  In other words, archives won't be portable.
388<p>
389This problem is addressed by creating another method of assigning serialization traits
390to user classes.  This is illustrated by the serialization for a
391<a target="nvp" href="../../../boost/serialization/nvp.hpp"><strong>name-value</strong> pair</a>.
392<p>
393Specifically, this entails deriving the template from a special class
394<a target="traits" href="../../../boost/serialization/traits.hpp">
395<code style="white-space: normal">boost::serialization::traits</code></a> which is specialized for a specific
396combination of serialization traits. 
397When looking up the serialization traits, the library first checks to see if this class has been
398used as a base class. If so, the corresponding traits are used.  Otherwise, the standard defaults
399are used. By deriving from a serialization traits class rather than relying upon Partial Template
400Specializaton, one can a apply serialization traits to a template and those traits will be
401the same across all known platforms.
402<p>
403The signature for the traits template is:
404<pre><code>
405template&lt;
406    class T,       
407    int Level,
408    int Tracking,
409    unsigned int Version = 0,
410    class ETII = BOOST_SERIALIZATION_DEFAULT_TYPE_INFO(T)
411&gt;
412struct traits
413</code></pre>
414and template parameters should be assigned according to the following table:
415<p>
416<table border>
417<tr><th align=left>parameter</th><th align=left>description</th><th align=left>permitted values</th><th align=left>default value</th></tr>
418<tr><td><code>T</code></td><td>target class</td><td>class name<T></td><td>none</td></tr>           
419<tr><td><code>Level</code></td><td>implementation level</td><td><code>not_serializable<br>primitive_type<br>object_serializable<br>object_class_info</code></td><td>none</td></tr> 
420<tr><td><code>Tracking</code></td><td>tracking level</td><td><code>track_never<br>track_selectivly<br>track_always</code></td><td>none</td></tr>
421<tr><td><code>Version</code></td><td><code>class version</td><td>unsigned integer</td><td><code>0</code></td></tr>
422<tr><td><code>ETTI</code></td><td><code>type_info</code> implementation</td><td><code>extended_type_info_typeid<br>extended_type_info_no_rtti</code></td><td>default <code>type_info implementation</code></td></tr>
423</table>
424
425<hr>
426<p><i>&copy; Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 2002-2004.
427Distributed under the Boost Software License, Version 1.0. (See
428accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
429</i></p>
430</body>
431</html>
Note: See TracBrowser for help on using the repository browser.