123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- <!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <!--
- (C) Copyright 2002-4 Robert Ramey - http://www.rrsd.com .
- Use, modification and distribution is subject to the Boost Software
- License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt)
- -->
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <link rel="stylesheet" type="text/css" href="../../../boost.css">
- <link rel="stylesheet" type="text/css" href="style.css">
- <title>Serialization - PIMPL</title>
- </head>
- <body link="#0000ff" vlink="#800080">
- <table border="0" cellpadding="7" cellspacing="0" width="100%" summary="header">
- <tr>
- <td valign="top" width="300">
- <h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../boost.png" border="0"></a></h3>
- </td>
- <td valign="top">
- <h1 align="center">Serialization</h1>
- <h2 align="center">PIMPL</h2>
- </td>
- </tr>
- </table>
- <hr>
- PIMPL is a C++ programming idiom described by Herb Sutter <a href="bibliography.html#10">[10]</a>
- which stands for "Private Implementation". It is also referred to as
- the "Handle Body Idiom". Included in this library is a program called
- <a href="../example/demo_pimpl.cpp" target="demo_impl_cpp">demo_pimpl.cpp</a>
- which illustrates how this is used. The file
- <a href="../example/demo_pimpl_A.cpp" target="demo_impl__Acpp">demo_pimpl_A.hpp</a>
- contains the declaration of the A class that hides its implementation
- by including a pointer to struct B that is only defined as a pointer.
- <pre><code>
- // class whose declaration is hidden by a pointer
- struct B;
- struct A {
- // class a contains a pointer to a "hidden" declaration
- B *pimpl;
- template<class Archive>
- void serialize(Archive & ar, const unsigned int file_version);
- A();
- };
- </code></pre>
- Serialization of A requires access to the definition of B. But that doesn't mean
- that it requires the this access from the header file. Since B is a pointer,
- a declaration of class B is sufficient. The implemenation of the serialization
- of A includes the definition of class B defined in the separately compiled module:
- <a href="../example/demo_pimpl_A.cpp" target="demo_impl_A_cpp">demo_pimpl_A.cpp</a>
- by:
- <pre><code>
- #include "demo_pimpl_A.hpp"
- // "hidden" definition of class B
- struct B {
- int b;
- template<class Archive>
- void serialize(Archive & ar, const unsigned int file_version){
- ar & b;
- }
- };
- A::A() :
- pimpl(new B)
- {}
- A::~A(){
- delete pimpl;
- }
- // now we can define the serialization for class A
- template<class Archive>
- void A::serialize(Archive & ar, const unsigned int file_version){
- ar & pimpl;
- }
- </code></pre>
- As described in <a href="bibliography.html#10">[10]</a> this brings the
- following advantages:
- <ul>
- <li>type "B" can be used without using its header.
- <li>implementation of B can be changed without generating a
- cascade of recompilations.
- </ul>
- So, we compile the modules and everything is fine. However when we
- link, we get an error. Two symbols are undefined:
- <pre><code>
- void A::serialize(boost::archive::text_oarchive & ar, const unsigned int file_version);
- void A::serialize(boost::archive::text_iarchive & ar, const unsigned int file_version);
- </code></pre>
- The problem is that when compiling the above code,
- there is no instantiation of the <code style="white-space: normal">serialize</code> template.
- There can't be as it's not "known" what types of archives
- the serialization is going to be used with. So these functions are "missing"
- when an attempt to link is made. The solution is to explicitly instantiate
- serialization code for those archives which are going to be used. In this
- example, including the the following code in any *.cpp file does just that:
- <pre></code>
- #include <boost/archive/text_iarchive.hpp>
- #include <boost/archive/text_oarchive.hpp>
- template void A::serialize<boost::archive::text_iarchive>(
- boost::archive::text_iarchive & ar,
- const unsigned int file_version
- );
- template void A::serialize<boost::archive::text_oarchive>(
- boost::archive::text_oarchive & ar,
- const unsigned int file_version
- );
- </code></pre>
- The program should now link as well as compile.
- <p>
- The downside of this is that one has to know which archives are going
- to be used with hidden serializations. This is an effect of using template
- driven code. One can invoke explicity instantiation for all known templates and
- presume that the linker will exclude unreferenced code. This should
- work but is platform dependent.
- <hr>
- <p><i>© Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 2002-2004.
- Distributed under the Boost Software License, Version 1.0. (See
- accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- </i></p>
- </body>
- </html>
|