11

ポリモーフィック クラスへのポインターをシリアル化しようとしていますShapeBOOST_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 つのオプションがあります。

  1. EXPORT_IN_MAIN動作しますが、私が望むものではありません。シリアル化を呼び出すコードは、PIMPL クラスの実装の詳細について知る必要はありません。

  2. EXPORT_IN_OBJECTコンパイルされますが、動作しません:boost::archive::archive_exceptionメッセージ付きの結果になりますunregistered void castdocumentationによると、これは、私が行ったように、を使用して基本クラスをシリアル化することで解決する必要がありますboost::serialization::base_objectが、役に立ちません。

  3. 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 を使用しています。

4

6 に答える 6

9

Boost.Serialization docs (1.44.0) のExporting Class Serializationには、次のように記載されています。


BOOST_CLASS_EXPORTアーカイブ クラス ヘッダーのいずれかを含む同じソース モジュールでは、コードがインスタンス化されます [...]

この機能を実装するには、 BOOST_CLASS_EXPORTコードをインスタンス化するアーカイブ クラス ヘッダーの後にマクロを記述し、含める必要があることに注意してください。したがって、を使用するコード BOOST_CLASS_EXPORTは次のようになります。

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
... // other archives

#include "a.hpp" // header declaration for class a
BOOST_CLASS_EXPORT(a)
... // other class headers and exports

[...]BOOST_CLASS_EXPORT他のシリアライゼーション特性で行うように「a.hpp」ヘッダー自体にインクルードする と、BOOST_CLASS_EXPORT呼び出される前にアーカイブ ヘッダーのインクルードに関する上記の規則に従うことが困難または不可能になります。これは BOOST_CLASS_EXPORT_KEY、ヘッダー宣言とBOOST_CLASS_EXPORT_IMPLEMENTクラス定義ファイルで を使用することによって最もよく対処できます。


于 2010-11-04T07:37:31.593 に答える
4

s11n.hシリアライゼーションを呼び出す CPP ファイルからインクルードされるヘッダーにすべてのシリアライゼーション コードを配置することになりました。基本的に、EXPORT_IN_MAIN上でスケッチしたシナリオですがBOOST_CLASS_EXPORT、別のファイルでマクロを呼び出しています。

s11n.hもちろん、これはコンパイル単位が1つだけ含まれている場合にのみ機能するため、今のところ機能しますが、実際の解決策ではありません...

于 2010-10-20T19:40:36.863 に答える
2

EXPORT_IN_OBJECT を使用できますが、BOOST_CLASS_EXPORT を含むファイルには、使用する予定のすべてのアーカイブ hpp ファイルも含まれている必要があります。

これは、BOOST_CLASS_EXPORT マクロが、各アーカイブが使用すると考える構造型情報を登録するためです (含めたアーカイブに基づいて暗黙的に決定されます)。

あなたの例では、EXPORT_IN_OBJECT を使用しますが、#include を export.cpp に追加します。

私たちのコードでは、使用するアーカイブを含む archives.hpp を作成し、BOOST_CLASS_EXPORT を使用する必要がある場所にそれを含めます。(そうすれば、アーカイブの公式リストが 1 つになります。)

欠点は、新しいアーカイブ タイプを使用することを決定したときにすべてを再構築する必要があることですが、ポリモーフィック アーカイブのサポートよりもはるかに使いやすいことがわかりました。

于 2010-11-03T20:42:17.393 に答える
1

この古いスレッドをチェックしてください。

http://lists.boost.org/boost-users/2005/01/9390.php

于 2010-08-10T18:52:04.177 に答える
0

各 .cpp に一意の BOOST_CLASS_EXPORT_GUID() を使用して、.cpp にのみ追加できます。ない.h

于 2014-03-27T14:54:09.933 に答える
0

この問題は、私の基底クラスがポリモーフィックではないことに気付くまで、私を狂わせました。つまり、「virtual」というキーワードはどこにも使用されていません。ポリモーフィックな動作は必要なかったからです。

これが私がそれを修正した方法です:

  1. 基本クラスのランダムなメソッドに「仮想」というキーワードを平手打ちしました。
  2. 派生クラスの .cpp ファイルに、次を追加しました。

    #include <boost/serialization/export.hpp>
    BOOST_CLASS_EXPORT(testnamespace::derivedclass)
    

これが私がしなければならなかったすべてです。

于 2014-08-07T23:17:22.217 に答える