derivation.html 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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 - Derivation from an Existing Archive</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">Derivation from an Existing Archive</h2>
  24. </td>
  25. </tr>
  26. </table>
  27. <hr>
  28. <dl class="page-index">
  29. </dl>
  30. <h3>Log Archive</h3>
  31. It may happen that one wants to create a new archive class by derivation from one
  32. of the included ones. Included is a sample program that shows how to derive a
  33. new archive from one of the ones included with the library. The first example is
  34. <a href="../example/demo_log.cpp" target="demo_log_cpp">
  35. demo_log.cpp</a>.
  36. <p>
  37. This derivation from the xml archive writes output in xml without the extra
  38. information required to read the data back into the application. It might be
  39. used to export one's data as simple xml for other applications or for logging
  40. data while debugging.
  41. <p>
  42. To this end it is derived from the included xml archive and the save functions for
  43. some types are specialized for this application.
  44. <p>
  45. The serialization library is
  46. implemented using the <b>C</b>uriously <b>R</b>ecurring <b>T</b>emplate
  47. <b>P</b>attern (<b>CRTP</b>). Also, all common code is factored out into
  48. separate modules to minimize code repetition. This makes derivation from
  49. an existing archive less straightforward than it would otherwise be.
  50. <p>
  51. This example illustrates several issues that have to be addressed when doing
  52. something like this
  53. <ol>
  54. <li><i>It is derived from</i> <code style="white-space: normal">xml_oarchive_impl<log_archive></code>
  55. <b>NOT</b> <code style="white-space: normal">xml_oarchive</code> <br>
  56. As described in the comments in
  57. <a href="../../../boost/archive/xml_oarchive.hpp" target="xml_oarchive_hpp">xml_oarchive.hpp</a>.
  58. <code style="white-space: normal">xml_oarchive</code> really a shorthand name for
  59. <code style="white-space: normal">xml_oarchive_impl&lt;xml_oarchive&gt;</code>. So we should derive
  60. from <code style="white-space: normal">xml_oarchive_impl&lt;log_archive&gt;</code> rather
  61. than <code style="white-space: normal">xml_oarchive</code>.
  62. <pre><code>
  63. class log_archive :
  64. // don't derive from xml_oarchive !!!
  65. public xml_oarchive_impl&lt;log_archive&gt;
  66. {
  67. ...
  68. </code></pre>
  69. <li><i>Note the</i> <code style="white-space: normal">log_archive</code> <i>between the</i> &lt;&gt;
  70. This is required so that base classes can downcast their <code style="white-space: normal">this</code> pointer
  71. to the most derived class. This is referred to as <b>C</b>uriously <b>R</b>ecurring
  72. <b>T</b>emplate <b>P</b>attern (<b>CRTP</b>) <a href="bibliography.html#11">[11]</a>.
  73. It is used to implement static polymorphism.
  74. <li><i>Base classes need to be explicitly given access to the derived class.</i>
  75. This can be done by making members public or by including friend declarations for
  76. the base classes.
  77. <pre><code>
  78. friend class detail::common_oarchive&lt;log_archive&gt;;
  79. friend class basic_xml_oarchive&lt;log_archive&gt;;
  80. friend class boost::serialization::save_access;
  81. </code></pre>
  82. <li><i></i>Reread <a target="detail" href="headers.html#archiveinternals">Archive Internals</a>.
  83. This describes the class hierarchy so that you know what to override.
  84. <li><i>Base class functions will usually need to be explicitly invoked.</i>
  85. We commonly specialize the function name <code style="white-space: normal">save_override</code>
  86. for saving primitives. Usage of a function name in a derived class
  87. "hides" similarly named functions of the base class. That is,
  88. function name overloading doesn't automatically
  89. include base classes. To address this, we can use:
  90. <pre><code>
  91. using xml_oarchive_impl&lt;derived_t&gt;::save;
  92. void save(const unsigned int t);
  93. ...
  94. </code></pre>
  95. which should work on conforming compilers. However, I have found
  96. that the following equivalent works on more compilers.
  97. <pre><code>
  98. // default fall through for any types not specified here
  99. template&lt;class T&gt;
  100. void save(const T & t){
  101. xml_oarchive_impl&lt;derived_t&gt;::save(t);
  102. }
  103. void save(const unsigned int t);
  104. ...
  105. </code></pre>
  106. so it's what I use.
  107. <li><i>Template definitions of base classes may have to be explicitly instantiated.</i>
  108. The demo includes
  109. <pre><code>
  110. // explicitly instantiate for this type of binary stream
  111. #include &lt;boost/archive/basic_binary_oprimitive.ipp&gt;
  112. </code></pre>
  113. for just this purpose. Failure to include required template definitions
  114. will result in undefined symbol errors when the program is linked.
  115. <li><i>Without alteration, this class cannot be further derived from.</i><br>
  116. Base classes using <b>CRTP</b> must be templates with a parameter corresponding to
  117. the most derived class. As presented here, this class doesn't qualify, so
  118. it cannot be used as a base class. In order to derive further from this class,
  119. it would have to be reorganized along the lines of the original <code style="white-space: normal">xml_oarchive</code>.
  120. Specifically, it would look something like:
  121. <pre><code>
  122. template&lt;class Archive&gt;
  123. class log_archive_impl :
  124. // don't derive from xml_oarchive !!!
  125. public xml_oarchive_impl&lt;Archive&gt;
  126. {
  127. ...
  128. );
  129. // do not derive from this class !!!
  130. class log_archive :
  131. public log_archive_impl&lt;log_archive&gt;
  132. {
  133. public:
  134. log_archive(std::ostream & os, unsigned int flags = 0) :
  135. log_archive_impl&lt;xml_oarchive&gt;(os, flags)
  136. {}
  137. };
  138. </code></pre>
  139. </ol>
  140. <hr>
  141. <p><i>&copy; Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 2002-2004.
  142. Distributed under the Boost Software License, Version 1.0. (See
  143. accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  144. </i></p>
  145. </body>
  146. </html>