Я пытаюсь сериализовать указатель на полиморфный класс Shape
. Поэтому мне нужно использовать макрос BOOST_CLASS_EXPORT
для определения GUID для каждого подкласса. Проблема: куда его поставить?
Позвольте мне сначала показать минимальный тестовый пример:
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;
}
В gcc я скомпилирую их с помощью
g++ -omain main.cpp export.cpp -Wl,-Bstatic -lboost_serialization-mt -Wl,-Bdynamic -DEXPORT_IN_XXX
Здесь export.cpp
может выглядеть немного глупо. В моей реальной ситуации он содержит охватывающий класс, который использует идиому PIMPL, и пытается сериализовать его (полиморфную) реализацию Shape
. Важным моментом является то, что BOOST_CLASS_EXPORT
может находиться в другом объектном файле, чем код, вызывающий сериализацию.
Итак, вот проблема: где использовать BOOST_CLASS_EXPORT
? У меня есть три варианта, которые можно активировать с помощью макросов EXPORT_IN_XXX
.
-
EXPORT_IN_MAIN
работает, но это не то, что я хочу. Код, вызывающий сериализацию, не должен знать о деталях реализации класса PIMPL. -
EXPORT_IN_OBJECT
компилируется, но не работает: в результате получаетсяboost::archive::archive_exception
с сообщениемunregistered void cast
. Согласно документации это должно быть разрешено путем сериализации базовых классов с помощьюboost::serialization::base_object
, как и я, но это не помогает. -
EXPORT_IN_HEADER
даже не компилируется. МакросBOOST_CLASS_EXPORT
расширяется до специализации шаблона (который мы хотели бы быть в файле заголовка), но также и для определения его статического члена. Поэтому я получаю ошибку компоновщика в отношенииmultiple definition of 'boost::archive::detail::init_guid<Rect>::guid_initializer'
.
Если это имеет значение, я использую g++ 4.4.3 и Boost 1.40.