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 - PIMPL</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">PIMPL</h2> 24 </td> 25 </tr> 26</table> 27<hr> 28PIMPL is a C++ programming idiom described by Herb Sutter <a href="bibliography.html#10">[10]</a> 29which stands for "Private Implementation". It is also referred to as 30the "Handle Body Idiom". Included in this library is a program called 31<a href="../example/demo_pimpl.cpp" target="demo_impl_cpp">demo_pimpl.cpp</a> 32which illustrates how this is used. The file 33<a href="../example/demo_pimpl_A.cpp" target="demo_impl__Acpp">demo_pimpl_A.hpp</a> 34contains the declaration of the A class that hides its implementation 35by including a pointer to struct B that is only defined as a pointer. 36<pre><code> 37// class whose declaration is hidden by a pointer 38struct B; 39 40struct A { 41 // class a contains a pointer to a "hidden" declaration 42 B *pimpl; 43 template<class Archive> 44 void serialize(Archive & ar, const unsigned int file_version); 45 A(); 46}; 47</code></pre> 48Serialization of A requires access to the definition of B. But that doesn't mean 49that it requires the this access from the header file. Since B is a pointer, 50a declaration of class B is sufficient. The implemenation of the serialization 51of A includes the definition of class B defined in the separately compiled module: 52 53<a href="../example/demo_pimpl_A.cpp" target="demo_impl_A_cpp">demo_pimpl_A.cpp</a> 54by: 55<pre><code> 56#include "demo_pimpl_A.hpp" 57 58// "hidden" definition of class B 59struct B { 60 int b; 61 template<class Archive> 62 void serialize(Archive & ar, const unsigned int file_version){ 63 ar & b; 64 } 65}; 66 67A::A() : 68 pimpl(new B) 69{} 70 71A::~A(){ 72 delete pimpl; 73} 74 75// now we can define the serialization for class A 76template<class Archive> 77void A::serialize(Archive & ar, const unsigned int file_version){ 78 ar & pimpl; 79} 80</code></pre> 81As described in <a href="bibliography.html#10">[10]</a> this brings the 82following advantages: 83<ul> 84 <li>type "B" can be used without using its header. 85 <li>implementation of B can be changed without generating a 86 cascade of recompilations. 87</ul> 88So, we compile the modules and everything is fine. However when we 89link, we get an error. Two symbols are undefined: 90<pre><code> 91void A::serialize(boost::archive::text_oarchive & ar, const unsigned int file_version); 92void A::serialize(boost::archive::text_iarchive & ar, const unsigned int file_version); 93</code></pre> 94The problem is that when compiling the above code, 95there is no instantiation of the <code style="white-space: normal">serialize</code> template. 96There can't be as it's not "known" what types of archives 97the serialization is going to be used with. So these functions are "missing" 98when an attempt to link is made. The solution is to explicitly instantiate 99serialization code for those archives which are going to be used. In this 100example, including the the following code in any *.cpp file does just that: 101<pre></code> 102#include <boost/archive/text_iarchive.hpp> 103#include <boost/archive/text_oarchive.hpp> 104 105template void A::serialize<boost::archive::text_iarchive>( 106 boost::archive::text_iarchive & ar, 107 const unsigned int file_version 108); 109template void A::serialize<boost::archive::text_oarchive>( 110 boost::archive::text_oarchive & ar, 111 const unsigned int file_version 112); 113</code></pre> 114The program should now link as well as compile. 115<p> 116The downside of this is that one has to know which archives are going 117to be used with hidden serializations. This is an effect of using template 118driven code. One can invoke explicity instantiation for all known templates and 119presume that the linker will exclude unreferenced code. This should 120work but is platform dependent. 121<hr> 122<p><i>© Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 2002-2004. 123Distributed under the Boost Software License, Version 1.0. (See 124accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 125</i></p> 126</body> 127</html> 128