Я пытаюсь сериализовать указатель на полиморфный класс Shape
. Поэтому мне нужно использовать BOOST_CLASS_EXPORT
macro для определить 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.
boost::archive::detail::init_guid<SomeClass>::guid_initializer
во время компиляции. Я очень озадачен, поэтому, если вы поняли это после того, как задали этот вопрос, я был бы очень признателен, если бы вы поделились !! Спасибо! - person bguiz   schedule 19.10.2010