traits.html 34 KB

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