|
SerializationPIMPL |
// 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();
};
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:
demo_pimpl_A.cpp
by:
#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;
}
As described in [10] this brings the
following advantages:
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);
The problem is that when compiling the above code,
there is no instantiation of the serialize
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:
#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 );The program should now link as well as compile.
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.
© Copyright Robert Ramey 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)