ポリモーフィック クラスへのポインターをシリアル化しようとしていますShape
。BOOST_CLASS_EXPORT
そのため、マクロを使用して各サブクラスの GUID を定義する必要があります。問題:どこに置く?
最初に最小限のテスト ケースを示します。
形状.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
マクロを使用して有効にできる 3 つのオプションがあります。
EXPORT_IN_MAIN
動作しますが、私が望むものではありません。シリアル化を呼び出すコードは、PIMPL クラスの実装の詳細について知る必要はありません。EXPORT_IN_OBJECT
コンパイルされますが、動作しません:boost::archive::archive_exception
メッセージ付きの結果になりますunregistered void cast
。documentationによると、これは、私が行ったように、を使用して基本クラスをシリアル化することで解決する必要がありますboost::serialization::base_object
が、役に立ちません。EXPORT_IN_HEADER
コンパイルさえしません。マクロBOOST_CLASS_EXPORT
は、テンプレートの特殊化 (ヘッダー ファイルに含めたい) に展開されますが、その中の静的メンバーの定義にも展開されます。そのため、a に関するリンカ エラーが発生しますmultiple definition of 'boost::archive::detail::init_guid<Rect>::guid_initializer'
。
問題があれば、g++ 4.4.3 と Boost 1.40 を使用しています。