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