I'm trying to serialize a pointer to a polymorphic class Shape
. So I need to use the BOOST_CLASS_EXPORT
macro to define a GUID for each subclass. The problem: where to put it?
Let me show a minimal test case first:
shapes.hpp
#include <boost/serialization/access.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/export.hpp>
class Shape {
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive &ar, unsigned int const version) {
// nothing to do
}
public:
virtual ~Shape() { }
};
class Rect : public Shape {
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive &ar, unsigned int const version) {
ar & boost::serialization::base_object<Shape>(*this);
}
public:
virtual ~Rect() { }
};
#ifdef EXPORT_IN_HEADER
BOOST_CLASS_EXPORT(Rect)
#endif
export.cpp
#include <boost/serialization/export.hpp>
#include "shapes.hpp"
#ifdef EXPORT_IN_OBJECT
BOOST_CLASS_EXPORT(Rect)
#endif
main.cpp
#include <iostream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/export.hpp>
#include "shapes.hpp"
#ifdef EXPORT_IN_MAIN
BOOST_CLASS_EXPORT(Rect)
#endif
int main() {
Shape *shape = new Rect();
boost::archive::text_oarchive ar(std::cout);
ar << shape;
}
On gcc, I compile these with
g++ -omain main.cpp export.cpp -Wl,-Bstatic -lboost_serialization-mt -Wl,-Bdynamic -DEXPORT_IN_XXX
Here, export.cpp
may look a bit silly. In my actual situation, it contains an enclosing class that uses the PIMPL idiom, and tries to serialize its (polymorphic) Shape
implementation. The important point is: the BOOST_CLASS_EXPORT
could be in a different object file than the code that invokes the serialization.
So here's the problem: where to use BOOST_CLASS_EXPORT
? I have three options, which can be enabled using the EXPORT_IN_XXX
macros.
EXPORT_IN_MAIN
works, but is not what I want. The code invoking the serialization should not need to know about the implementation details of the PIMPL class.EXPORT_IN_OBJECT
compiles, but does not work: it results in aboost::archive::archive_exception
with the messageunregistered void cast
. According to the documentation, this should be solved by serializing base classes usingboost::serialization::base_object
, like I did, but it doesn't help.EXPORT_IN_HEADER
does not even compile. The macroBOOST_CLASS_EXPORT
expands to a template specialization (which we'd like to be in the header file), but also to the definitiof of a static member therein. So I get a linker error about amultiple definition of 'boost::archive::detail::init_guid<Rect>::guid_initializer'
.
If it matters, I'm using g++ 4.4.3 and Boost 1.40.