]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/serialization/doc/traits.html
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / serialization / doc / traits.html
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 .
5 Use, modification and distribution is subject to the Boost Software
6 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 http://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="#wrappers">Wrappers</a>
36 <dt><a href="#bitwise">Bitwise Serialization</a>
37 <dt><a href="#templates">Template Serialization Traits</a>
38 <dt><a href="#compiletime_messages">Compile Time Warnings and Errors</a>
39 </dl>
40 Serialization of data depends on the type of the data. For example, for
41 primitive types such as <code style="white-space: normal">int</code>, it wouldn't make sense to save
42 a version number in the archive. Likewise, for a data type that is never
43 serialized through a pointer, it would (almost) never make sense to track
44 the address of objects saved to/loaded from the archive as it will never
45 be saved/loaded more than once in any case. Details of
46 serialization for a particular data type will vary depending on the
47 type, the way it is used and specifications of the programmer.
48 <p>
49 One can alter the manner in which a particular data type is serialized
50 by specifying one or more <strong>class serialization traits</strong>.
51 It is not generally necessary for the programmer to explictly assign
52 traits to his classes as there are default values for all traits.
53 If the default values are not appropriate they can be assigned by the programmer.
54 A template is used to associate a typename with a constant. For example
55 see <a href="../../../boost/serialization/version.hpp" target="version_hpp">
56 version.hpp</a>.
57 <h3><a name="version">Version</a></h3>
58 This header file includes the following code:
59
60 <pre><code>
61 namespace boost {
62 namespace serialization {
63 template&lt;class T&gt;
64 struct version
65 {
66 BOOST_STATIC_CONSTANT(unsigned int, value = 0);
67 };
68 } // namespace serialization
69 } // namespace boost
70 </code></pre>
71
72 For any class <code style="white-space: normal">T</code>, The default definition
73 of <code style="white-space: normal">boost::serialization::version&lt;T&gt;::value</code> is 0.
74 If we want to assign a value of 2 as the version for class <code style="white-space: normal">my_class</code>
75 we specialize the version template:
76 <pre><code>
77 namespace boost {
78 namespace serialization {
79 struct version&lt;my_class&gt;
80 {
81 BOOST_STATIC_CONSTANT(unsigned int, value = 2);
82 };
83 } // namespace serialization
84 } // namespace boost
85 </code></pre>
86 Now whenever the version number for class <code style="white-space: normal">my_class</code> is required,
87 the value 2 will be returned rather than the default value of 0.
88 <p>
89 To diminish typing and enhance readability, a macro is defined
90 so that instead of the above, we could write:
91 <pre><code>
92 BOOST_CLASS_VERSION(my_class, 2)
93 </code></pre>
94 which expands to the code above.
95
96 <h3><a name="level">Implementation Level</a></h3>
97 In the same manner as the above, the "level" of implementation of serialization is
98 specified. The header file <a href="../../../boost/serialization/level.hpp"
99 target="level_hpp">level.hpp</a> defines the following.
100 <pre><code>
101 // names for each level
102 enum level_type
103 {
104 // Don't serialize this type. An attempt to do so should
105 // invoke a compile time assertion.
106 not_serializable = 0,
107 // write/read this type directly to the archive. In this case
108 // serialization code won't be called. This is the default
109 // case for fundamental types. It presumes a member function or
110 // template in the archive class that can handle this type.
111 // there is no runtime overhead associated reading/writing
112 // instances of this level
113 primitive_type = 1,
114 // Serialize the objects of this type using the objects "serialize"
115 // function or template. This permits values to be written/read
116 // to/from archives but includes no class or version information.
117 object_serializable = 2,
118 ///////////////////////////////////////////////////////////////////
119 // once an object is serialized at one of the above levels, the
120 // corresponding archives cannot be read if the implementation level
121 // for the archive object is changed.
122 ///////////////////////////////////////////////////////////////////
123 // Add class information to the archive. Class information includes
124 // implementation level, class version and class name if available.
125 object_class_info = 3,
126 };
127 </code></pre>
128 Using a macro defined in <code style="white-space: normal">level.hpp</code> we can specify
129 that <code style="white-space: normal">my_class</code> should be serialized along with its version number:
130 <pre><code>
131 BOOST_CLASS_IMPLEMENTATION(my_class, boost::serialization::object_class_info)
132 </code></pre>
133 If implementation level is not explicitly assigned, the system uses
134 a default according to the following rules.
135 <ul>
136 <li>if the data type is <code style="white-space: normal">volatile</code>
137 assign <code style="white-space: normal">not_serializable</code>
138 <li>else if it's an enum or fundamental type assign <code style="white-space: normal">primitive_type</code>
139 <li>else assign <code style="white-space: normal">object_class_info</code>
140 </ul>
141 That is, for most user defined types, objects will be serialized along with
142 class version information. This will permit one to maintain backward
143 compatibility with archives which contain previous versions. However, with this
144 ability comes a small runtime cost. For types whose definition will "never"
145 change, efficiency can be gained by specifying <code style="white-space: normal">object_serializable</code>
146 to override the default setting of <code style="white-space: normal">object_class_info</code>.
147 For example,
148 this has been done for the
149 <a href="../../../boost/serialization/binary_object.hpp" target="binary_object_hpp">
150 binary_object wrapper</a>
151
152 <h3><a name="tracking">Object Tracking</a></h3>
153 Depending on the way a type is used, it may be necessary or convenient to
154 track the address of objects saved and loaded. For example, this is generally
155 necessary while serializing objects through a pointer in order to be sure
156 that multiple identical objects are not created when an archive is loaded.
157 This "tracking behavior" is controlled by the type trait defined in the header
158 file <a href="../../../boost/serialization/tracking.hpp" target="tracking_hpp">tracking.hpp</a>
159 which defines the following:
160 <pre><code>
161 // names for each tracking level
162 enum tracking_type
163 {
164 // never track this type
165 track_never = 0,
166 // track objects of this type if the object is serialized through a
167 // pointer.
168 track_selectively = 1,
169 // always track this type
170 track_always = 2
171 };
172 </code></pre>
173 A corresponding macro is defined so that we can use:
174 <pre><code>
175 BOOST_CLASS_TRACKING(my_class, boost::serialization::track_never)
176 </code></pre>
177 Default tracking traits are:
178 <ul>
179 <li>For primitive, <code style="white-space: normal">track_never</code>.
180 <li>For pointers, <code style="white-space: normal">track_never</code>.
181 That is, addresses of addresses are not tracked by default.
182 <li>All current serialization wrappers such as <code style="white-space: normal">boost::serialization::nvp</code>,
183 <code style="white-space: normal">track_never</code>.
184 <li>For all other types, <code style="white-space: normal">track_selectively</code>.
185 That is addresses of serialized objects are tracked if and only if
186 one or more of the following is true:
187 <ul>
188 <li>an object of this type is anywhere in the program serialized
189 through a pointer.
190 <li>the class is explicitly "exported" - see below.
191 <li>the class is explicitly "registered" in the archive
192 </ul>
193 </ul>
194
195 <p>
196 The default behavior is almost always the most convenient one. However,
197 there a few cases where it would be desirable to override the
198 default. One case is that of a virtual base class. In a diamond
199 heritance structure with a virtual base class, object tracking
200 will prevent redundant save/load invocations. So here is one
201 case where it might be convenient to override the default tracking
202 trait. <i>(Note: in a future version the default will be reimplemented
203 to automatically track classes used as virtual bases).</i> This
204 situation is demonstrated by
205 <a href="../test/test_diamond.cpp" target="test_diamond_cpp">test_diamond.cpp</a>
206 included with the library.
207
208 <h3><a name="export">Export Key</a></h3>
209
210 When serializing a derived class through a virtual base class pointer,
211 two issues may arise.
212 <ul>
213 <li> The code in the derived class might never be explicitly
214 referred to. Such code will never be instantiated.
215 <p>
216 This is addressed by invoking
217 <code style="white-space: normal">BOOST_CLASS_EXPORT_IMPLEMENT(T)</code>
218 in the file which defines (implements) the class T.
219 This ensures that code for the derived class T will
220 be explicity instantiated.
221 <li> There needs to be some sort of identifier which can
222 be used to select the code to be invoked when the object
223 is loaded.
224 Standard C++ does implement <code style="white-space: normal">typeid()</code> which can be
225 used to return a unique string for the class. This is not entirely
226 statisfactory for our purposes for the following reasons:
227 <ul>
228 <li>There is no guarantee that the string is the same across platforms.
229 This would then fail to support portable archives.
230 <li>In using code modules from various sources, classes may have
231 to be wrapped in different namespaces in different programs.
232 <li>There might be classes locally defined in different code modules
233 that have the same name.
234 <li>There might be classes with different names that we want to
235 consider equivalent for purposes of serialization.
236 </ul>
237 <p>
238 So in the serialization library, this is addressed by invoking
239 <code style="white-space: normal">BOOST_CLASS_EXPORT_KEY2(my_class, "my_class_external_identifier")</code>
240 in the header file which declares the class.
241 In a large majority of applications, the class name works just fine
242 for the external identifier string so the following short cut is
243 defined -
244 <code style="white-space: normal">BOOST_CLASS_EXPORT_KEY(my_class)</code>.
245 </ul>
246 For programs which consist of only one module - that is
247 programs which do not use DLLS, one can specify
248 <code style="white-space: normal">BOOST_CLASS_EXPORT(my_class)</code>
249 or
250 <code style="white-space: normal">BOOST_CLASS_EXPORT_GUID(my_class, "my_class_external_identifier")</code>
251 in either the declaration header or definition. These macros
252 expand to invocation of both of the macros described above.
253 <i>(<b>GUID</b> stands for <b>G</b>lobally <b>U</b>nique <b>ID</b>entfier.)</i>
254 <p>
255 <i>(<a target="detail" href="special.html#export">Elsewhere</a>
256 in this manual, the serialization of derived classes is addressed in detail.)</i>
257 <p>
258 The header file
259 <a href="../../../boost/serialization/export.hpp" target="export_hpp">export.hpp</a>
260 contains all macro definitions described here.
261 The library will throw a runtime exception if
262 <ul>
263 <li> A type not explicitly referred to is not exported.
264 <li> Serialization code for the same type is instantiated
265 in more than one module (or DLL).
266 </ul>
267
268 <h3><a name="abstract">Abstract</a></h3>
269 When serializing an object through a pointer to its base class,
270 the library needs to determine whether or not the base is abstract
271 (i.e. has at least one virtual function). The library uses the
272 type trait macro <code style="white-space: normal">BOOST_IS_ABSTRACT(T)</code>
273 to do this. Not all compilers support this type trait and corresponding
274 macro. To address this, the macro <code style="white-space: normal">
275 BOOST_SERIALIZATION_ASSUME_ABSTRACT(T)</code> has been
276 implemented to permit one to explicitly indicate that a specified
277 type is in fact abstract. This will guarentee that
278 <code style="white-space: normal">BOOST_IS_ABSTRACT</code>
279 will return the correct value for all compilers.
280
281 <h3><a name="typeinfo">Type Information Implementation</a></h3>
282 This last trait is also related to the serialization of objects
283 through a base class pointer. The implementation of this facility
284 requires the ability to determine at run time the true type of the
285 object that a base class pointer points to. Different serialization
286 systems do this in different ways. In our system, the default method
287 is to use the function <code style="white-space: normal">typeid(...)</code> which is available
288 in systems which support <b>RTTI</b> (<b>R</b>un <b>T</b>ime
289 <b>T</b>ype <b>I</b>nformation).
290 This will be satisfactory in almost all cases and most users of this
291 library will lose nothing in skipping this section of the manual.
292 <p>
293 However, there are some cases where the default type determination
294 system is not convenient. Some platforms might not support
295 RTTI or it may have been disabled in order to speed execution
296 or for some other reason. Some applications, E.G. runtime linking
297 of plug-in modules, can't depend on C++ RTTI to determine the
298 true derived class. RTTI only returns the correct type for polymorphic
299 classes - classes with at least one virtual function. If any of these
300 situations applies, one may substitute his own implementation of
301 <code style="white-space: normal">extended_type_info</code>
302 <p>
303 The interface to facilities required to implement serialization is defined in
304 <a href="../../../boost/serialization/extended_type_info.hpp"
305 target="extended_type_info_hpp">extended_type_info.hpp</a>.
306
307 Default implementation of these facilities based on <code style="white-space: normal">typeid(...)</code>
308 is defined in
309
310 <a href="../../../boost/serialization/extended_type_info_typeid.hpp"
311 target="extended_type_info_typeid_hpp">extended_type_info_typeid.hpp</a>.
312
313 An alternative implementation based on exported class identifiers
314 is defined in
315 <a href="../../../boost/serialization/extended_type_info_no_rtti.hpp"
316 target="extended_type_info_rtti_hpp">extended_type_info_no_rtti.hpp</a>.
317 <p>
318 By invoking the macro:
319 <pre><code>
320 BOOST_CLASS_TYPE_INFO(
321 my_class,
322 extended_type_info_no_rtti&lt;my_class&gt;
323 )
324 </code></pre>
325 we can assign the type information implementation to each class on a case by
326 case basis. There is no requirement that all classes in a program use the same
327 implementation of <code style="white-space: normal">extended_type_info</code>. This supports the concept
328 that serialization of each class is specified "once and for all" in a header
329 file that can be included in any project without change.
330 <p>
331 This is illustrated by the test program
332 <a href="../test/test_no_rtti.cpp" target="test_no_rtti_cpp">test_no_rtti.cpp</a>.
333 Other implementations are possible and might be necessary for
334 certain special cases.
335
336 <h3><a name="wrappers">Wrappers</a></h3>
337 Archives need to treat wrappers differently from other types since, for example,
338 they usually are non-const objects while output archives require that any
339 serialized object (with the exception of a wrapper) be const.
340
341 This header file <a href="../../../boost/serialization/wrapper.hpp">wrapper.hpp</a>
342 includes the following code:
343
344 <pre><code>
345 namespace boost {
346 namespace serialization {
347 template&lt;class T&gt;
348 struct is_wrapper
349 : public mpl::false_
350 {};
351 } // namespace serialization
352 } // namespace boost
353 </code></pre>
354
355 For any class <code style="white-space: normal">T</code>, The default definition
356 of <code style="white-space: normal">boost::serialization::is_wrapper&lt;T&gt;::value</code> is thus false.
357
358 If we want to declare that a class <code style="white-space: normal">my_class</code>
359 is a wrapper we specialize the version template:
360 <pre><code>
361 namespace boost {
362 namespace serialization {
363 struct is_wrapper&lt;my_class&gt;
364 : mpl::true_
365 {};
366 } // namespace serialization
367 } // namespace boost
368 </code></pre>
369 <p>
370 To diminish typing and enhance readability, a macro is defined
371 so that instead of the above, we could write:
372 <pre><code>
373 BOOST_CLASS_IS_WRAPPER(my_class)
374 </code></pre>
375 which expands to the code above.
376
377 <h3><a name="bitwise">Bitwise Serialization</a></h3>
378 Some simple classes could be serialized just by directly copying all bits
379 of the class. This is, in particular, the case for POD data types containing
380 no pointer members, and which are neither versioned nor tracked. Some archives,
381 such as non-portable binary archives can make us of this information to
382 substantially speed up serialization.
383
384 To indicate the possibility of bitwise serialization the type trait defined
385 in the header
386 file <a href="../../../boost/serialization/is_bitwise_serializable.hpp" target="is_bitwise_serializable">is_bitwise_serializable.hpp</a>
387 is used:
388 <pre><code>
389 namespace boost { namespace serialization {
390 template<class T>
391 struct is_bitwise_serializable
392 : public is_arithmetic<T>
393 {};
394 } }
395 </code></pre>
396 is used, and can be specialized for other classes. The specialization
397 is made easy by the corresponding macro:
398 <pre><code>
399 BOOST_IS_BITWISE_SERIALIZABLE(my_class)
400 </code></pre>
401
402 <h3><a name="templates">Template Serialization Traits</a></h3>
403 In some instances it might be convenient to assign serialization traits
404 to a whole group of classes at once. Consider, the name-value pair
405 wrapper
406 <pre><code>
407 template&lt;class T&gt;
408 struct nvp : public std::pair&lt;const char *, T *&gt;
409 {
410 ...
411 };
412 </code></pre>
413 used by XML archives to associate a name with a data variable of type T.
414 These data types are never tracked and never versioned. So one might
415 want to specify:
416 <pre><code>
417 BOOST_CLASS_IMPLEMENTATION(nvp&lt;T&gt;, boost::serialization::level_type::object_serializable)
418 BOOST_CLASS_TRACKING(nvp&lt;T&gt;, boost::serialization::track_never)
419 </code></pre>
420 Examination of the definition of these macros reveals that they won't expand
421 to sensible code when used with a template argument. So rather than using the
422 convenience macros, use the original definitions
423 <pre><code>
424 template&lt;class T&gt;
425 struct implementation_level&lt;nvp&lt;T&gt; &gt;
426 {
427 typedef mpl::integral_c_tag tag;
428 typedef mpl::int_&lt;object_serializable&gt; type;
429 BOOST_STATIC_CONSTANT(
430 int,
431 value = implementation_level::type::value
432 );
433 };
434
435 // nvp objects are generally created on the stack and are never tracked
436 template&lt;class T&gt;
437 struct tracking_level&lt;nvp&lt;T&gt; &gt;
438 {
439 typedef mpl::integral_c_tag tag;
440 typedef mpl::int_&lt;track_never&gt; type;
441 BOOST_STATIC_CONSTANT(
442 int,
443 value = tracking_level::type::value
444 );
445 };
446 </code></pre>
447 to assign serialization traits to all classes generated by the template
448 <code style="white-space: normal">nvp&lt;T&gt;</code>
449 <p>
450
451 Note that it is only possible to use the above method to assign traits to
452 templates when using compilers which correctly support Partial Template Specialization.
453
454 One's first impulse might be to do something like:
455
456 <pre><code>
457 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
458 template&lt;class T&gt;
459 struct implementation_level&lt;nvp&lt;T&gt; &gt;
460 {
461 ... // see above
462 };
463
464 // nvp objects are generally created on the stack and are never tracked
465 template&lt;class T&gt;
466 struct tracking_level&lt;nvp&lt;T&gt; &gt;
467 {
468 ... // see above
469 };
470 #endif
471 </code></pre>
472 This can be problematic when one wants to make his code <strong>and archives</strong>
473 portable to other platforms. It means the objects will be serialized differently
474 depending on the platform used. This implies that objects saved from one platform
475 won't be loaded properly on another. In other words, archives won't be portable.
476 <p>
477 This problem is addressed by creating another method of assigning serialization traits
478 to user classes. This is illustrated by the serialization for a
479 <a target="nvp" href="../../../boost/serialization/nvp.hpp"><strong>name-value</strong> pair</a>.
480 <p>
481 Specifically, this entails deriving the template from a special class
482 <a target="traits" href="../../../boost/serialization/traits.hpp">
483 <code style="white-space: normal">boost::serialization::traits</code></a> which is specialized for a specific
484 combination of serialization traits.
485 When looking up the serialization traits, the library first checks to see if this class has been
486 used as a base class. If so, the corresponding traits are used. Otherwise, the standard defaults
487 are used. By deriving from a serialization traits class rather than relying upon Partial Template
488 Specializaton, one can a apply serialization traits to a template and those traits will be
489 the same across all known platforms.
490 <p>
491 The signature for the traits template is:
492 <pre><code>
493 template&lt;
494 class T,
495 int Level,
496 int Tracking,
497 unsigned int Version = 0,
498 class ETII = BOOST_SERIALIZATION_DEFAULT_TYPE_INFO(T),
499 class IsWrapper = mpl::false_
500 &gt;
501 struct traits
502 </code></pre>
503 and template parameters should be assigned according to the following table:
504 <p>
505 <table border>
506 <tr><th align=left>parameter</th><th align=left>description</th><th align=left>permitted values</th><th align=left>default value</th></tr>
507 <tr><td><code>T</code></td><td>target class</td><td>class name<T></td><td>none</td></tr>
508 <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>
509 <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>
510 <tr><td><code>Version</code></td><td><code>class version</td><td>unsigned integer</td><td><code>0</code></td></tr>
511 <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>
512 <tr><td><code>IsWrapper</code></td><td><code></code>is the type a wrapper?</td><td><code>mpl::false_<br>mpl::true_</code></td><td><code>mpl::false_</code></td></tr>
513 </table>
514
515 <h3><a name="compiletime_messages">Compile Time Warnings and Errors</a></h3>
516 Some serialization traits can conflict with other ones. Sometimes these conflicts
517 will result in erroneous behavior (E.G. creating of archives which could not be read)
518 and other times they represent a probable misconception on the part of the
519 library user which could result in suprising behavior. To the extent possible,
520 these conflicts are detected at compile time and errors (BOOST_STATIC_ASSERT)
521 or warnings (BOOST_STATIC_WARNING) are generated. They are generated in a
522 compiler dependent manner which should show a chain of instantiation
523 to the point where the error/warning is detected. Without this capability,
524 it would be very hard to track down errors or unexpected behavior in library
525 usage. Here is a list of the conflicts trapped:
526
527 <dl>
528 <dt><h2><a name="object_level">object_level</a> - error</h2></dt>
529 <dd>
530 This error traps attempts to serialize types whose
531 implentation level is set to non_serializable.
532 </dd>
533 <dt><h2><a name="object_versioning">object_versioning</a> - error</h2></dt>
534 <dd>
535 It's possible that for efficiency reasons, a type can be
536 assigned a serialization level which doesn't include type information
537 in the archive. This would preclude the assignment
538 of a new version number to the type. This error
539 traps attempts to assign a version number in this case.
540 This has to be a user error.
541 </dd>
542
543 <dt><h2><a name="object_tracking">object_tracking</a> - warning</h2></dt>
544 <dd>
545 The following code will display a message when compiled:
546
547 <code style="white-space: normal"><pre>
548 T t;
549 ar &lt;&lt; t;
550 </pre></code>
551
552 unless the tracking_level serialization trait is set to "track_never". The following
553 will compile without problem:
554
555 <code style="white-space: normal"><pre>
556 const T t
557 ar &lt;&lt; t;
558 </pre></code>
559
560 Likewise, the following code will trap at compile time:
561
562 <code style="white-space: normal"><pre>
563 T * t;
564 ar >> t;
565 </pre></code>
566
567 if the tracking_level serialization trait is set to "track_never".
568 <p>
569
570 The following case illustrates the function of this message.
571 It was originally used as an example in the
572 mailing list by Peter Dimov.
573
574 <code style="white-space: normal"><pre>
575 class construct_from
576 {
577 ...
578 };
579
580 void main(){
581 ...
582 Y y;
583 construct_from x(y);
584 ar &lt;&lt; x;
585 }
586 </pre></code>
587
588 Suppose that the above message is not displayed and the code is used as is.
589 <ol>
590 <li>this example compiles and executes fine. No tracking is done because
591 construct_from has never been serialized through a pointer. Now some time
592 later, the next programmer(2) comes along and makes an enhancement. He
593 wants the archive to be sort of a log.
594
595 <code style="white-space: normal"><pre>
596 void main(){
597 ...
598 Y y;
599 construct_from x(y);
600 ar &lt;&lt; x;
601 ...
602 x.f(); // change x in some way
603 ...
604 ar &lt;&lt; x
605 }
606 </pre></code>
607 <p>
608 Again no problem. He gets two different of copies in the archive, each one is different.
609 That is he gets exactly what he expects and is naturally delighted.
610 <p>
611 <li>Now sometime later, a third programmer(3) sees construct_from and says -
612 oh cool, just what I need. He writes a function in a totally disjoint
613 module. (The project is so big, he doesn't even realize the existence of
614 the original usage) and writes something like:
615
616 <code style="white-space: normal"><pre>
617 class K {
618 shared_ptr &lt;construct_from&gt; z;
619 template &lt;class Archive&gt;
620 void serialize(Archive & ar, const unsigned version){
621 ar &lt;&lt; z;
622 }
623 };
624 </pre></code>
625
626 <p>
627 He builds and runs the program and tests his new functionality. It works
628 great and he's delighted.
629 <p>
630 <li>Things continue smoothly as before. A month goes by and it's
631 discovered that when loading the archives made in the last month (reading the
632 log). Things don't work. The second log entry is always the same as the
633 first. After a series of very long and increasingly acrimonius email exchanges,
634 it's discovered
635 that programmer(3) accidently broke programmer(2)'s code .This is because by
636 serializing via a pointer, the "log" object is now being tracked. This is because
637 the default tracking behavior is "track_selectively". This means that class
638 instances are tracked only if they are serialized through pointers anywhere in
639 the program. Now multiple saves from the same address result in only the first one
640 being written to the archive. Subsequent saves only add the address - even though the
641 data might have been changed. When it comes time to load the data, all instances of the log record show the same data.
642 In this way, the behavior of a functioning piece of code is changed due the side
643 effect of a change in an otherwise disjoint module.
644 Worse yet, the data has been lost and cannot be recovered from the archives.
645 People are really upset and disappointed with boost (at least the serialization system).
646 <p>
647 <li>
648 After a lot of investigation, it's discovered what the source of the problem is
649 and class construct_from is marked "track_never" by including:
650 <code style="white-space: normal"><pre>
651 BOOST_CLASS_TRACKING(construct_from, track_never)
652 </pre></code>
653 <li>Now everything works again. Or - so it seems.
654 <p>
655 <li><code style="white-space: normal">shared_ptr&lt;construct_from&gt;</code>
656 is not going to have a single raw pointer shared amongst the instances. Each loaded
657 <code style="white-space: normal">shared_ptr&lt;construct_from&gt;</code> is going to
658 have its own distinct raw pointer. This will break
659 <code style="white-space: normal">shared_ptr</code> and cause a memory leak. Again,
660 The cause of this problem is very far removed from the point of discovery. It could
661 well be that the problem is not even discovered until after the archives are loaded.
662 Now we not only have a difficult to find and fix program bug, but we have a bunch of
663 invalid archives and lost data.
664 </ol>
665
666 <p>Now consider what happens when the message is displayed:
667
668 <ol>
669 <p>
670 <li>Right away, the program traps at
671 <code style="white-space: normal"><pre>
672 ar &lt;&lt; x;
673 </pre></code>
674 <p>
675 <li>The programmer curses (another %^&*&* hoop to jump through). He's in a
676 hurry (and who isn't) and would prefer not to <code style="white-space: normal">const_cast</code>
677 - because it looks bad. So he'll just make the following change an move on.
678 <code style="white-space: normal"><pre>
679 Y y;
680 const construct_from x(y);
681 ar &lt;&lt; x;
682 </pre></code>
683 <p>
684 Things work fine and he moves on.
685 <p>
686 <li>Now programer (2) wants to make his change - and again another
687 annoying const issue;
688 <code style="white-space: normal"><pre>
689 Y y;
690 const construct_from x(y);
691 ...
692 x.f(); // change x in some way ; compile error f() is not const
693 ...
694 ar &lt;&lt; x
695 </pre></code>
696 <p>
697 He's mildly annoyed now he tries the following:
698 <ul>
699 <li>He considers making f() a const - but presumably that shifts the const
700 error to somewhere else. And he doesn't want to fiddle with "his" code to
701 work around a quirk in the serializaition system
702 <p>
703 <li>He removes the <code style="white-space: normal">const</code>
704 from <code style="white-space: normal">const construct_from</code> above - damn now he
705 gets the trap. If he looks at the comment code where the
706 <code style="white-space: normal">BOOST_STATIC_ASSERT</code>
707 occurs, he'll do one of two things
708 <ol>
709 <p>
710 <li>This is just crazy. Its making my life needlessly difficult and flagging
711 code that is just fine. So I'll fix this with a <code style="white-space: normal">const_cast</code>
712 and fire off a complaint to the list and mabe they will fix it.
713 In this case, the story branches off to the previous scenario.
714 <p>
715 <li>Oh, this trap is suggesting that the default serialization isn't really
716 what I want. Of course in this particular program it doesn't matter. But
717 then the code in the trap can't really evaluate code in other modules (which
718 might not even be written yet). OK, I'll add the following to my
719 construct_from.hpp to solve the problem.
720 <code style="white-space: normal"><pre>
721 BOOST_CLASS_TRACKING(construct_from, track_never)
722 </pre></code>
723 </ol>
724 </ul>
725 <p>
726 <li>Now programmer (3) comes along and make his change. The behavior of the
727 original (and distant module) remains unchanged because the
728 <code style="white-space: normal">construct_from</code> trait has been set to
729 "track_never" so he should always get copies and the log should be what we expect.
730 <p>
731 <li>But now he gets another trap - trying to save an object of a
732 class marked "track_never" through a pointer. So he goes back to
733 construct_from.hpp and comments out the
734 <code style="white-space: normal">BOOST_CLASS_TRACKING</code> that
735 was inserted. Now the second trap is avoided, But damn - the first trap is
736 popping up again. Eventually, after some code restructuring, the differing
737 requirements of serializating <code style="white-space: normal">construct_from</code>
738 are reconciled.
739 </ol>
740 Note that in this second scenario
741 <ul>
742 <li>all errors are trapped at compile time.
743 <li>no invalid archives are created.
744 <li>no data is lost.
745 <li>no runtime errors occur.
746 </ul>
747
748 It's true that these messages may sometimes flag code that is currently correct and
749 that this may be annoying to some programmers. However, this example illustrates
750 my view that these messages are useful and that any such annoyance is a small price to
751 pay to avoid particularly vexing programming errors.
752
753 </dd>
754
755 <dt><h2><a name="pointer_level">pointer_level</a> - warning</h2></dt>
756 <dd>
757 This trap addresses the following situaion when serializing
758 a pointer:
759 <ul>
760 <li>A type doesn't save class information in the
761 archive. That is, the serialization trait implementation
762 level <= object_serializable.
763 <li>Tracking for this type is set to "track selectively"
764 in this case, indication that an object is tracked is
765 not stored in the archive itself - see level == object_serializable.
766 Since class information is not saved in the archive, the existence
767 or absence of the operation ar << T * anywhere else in the
768 program is used to infer that an object of this type should be tracked.
769 <p>
770 A problem arises when a program which reads an archive
771 includes the operation ar >> T * so that tracking information
772 will be included in the archive. When a program which
773 creates the archive doesn't include ar << T it is presumed
774 that the archive doesn't include tracking information and
775 the archive will fail to load. Also the reverse situation could
776 trigger a similar problem.
777 <p>
778 Though this situation is unlikely for several reasones,
779 it is possible - hence this warning.
780 </ul>
781 So if your program traps here, consider changing the
782 tracking or implementation level traits - or not
783 serializing via a pointer.
784 </dd>
785
786 <dt><h2><a name="pointer_tracking">pointer_tracking</a> - warning</h2></dt>
787 <dd>
788 Serializing an object of a type marked "track_never" through a pointer
789 could result in creating more objects than were saved! There are cases
790 in which a user might really want to do this so we leave it as a warning.
791 </dd>
792
793 <dt><h2><a name="const_loading">const_loading</a> - error</h2></dt>
794 <dd>
795 One cannot load data into a "const" object unless it's a
796 wrapper around some other non-const object.
797 </dd>
798 </dl>
799
800 <hr>
801 <p><i>&copy; Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 2002-2004 and Matthias Troyer 2006.
802 Distributed under the Boost Software License, Version 1.0. (See
803 accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
804 </i></p>
805 </body>
806 </html>