2

Boost のシリアライゼーション ライブラリ(チュートリアルを参照)を理解しようとしていますが、クラスをシリアライズする非侵入的な方法が非常に気に入っています。

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

class gps_position
{
public:
    int degrees;
    int minutes;
    float seconds;
    gps_position(){};
    gps_position(int d, int m, float s) :
        degrees(d), minutes(m), seconds(s)
    {}
};

namespace boost {
namespace serialization {

template<class Archive>
void serialize(Archive & ar, gps_position & g, const unsigned int version)
{
    ar & g.degrees;
    ar & g.minutes;
    ar & g.seconds;
}

} // namespace serialization
} // namespace boost

このメソッドは、「gps_position」クラスをシリアル化するために使用できる関数「serialise」を提供しますが、この関数がいったんこの関数を取得すると、クラス自体がシリアル化可能(つまり、シリアル化/逆シリアル化に関してプリミティブのように機能する)かどうかはわかりません。作成された場合、またはそのために侵入的な方法を使用する必要がある場合...

つまり、たとえば「gps_position」インスタンスのベクトルを含む別のクラスがある場合、Boost は、「gps_position」パラメーターに一致する Boost::serialization 名前空間でオーバーロードされた「serialize」関数を探すことを認識します。親クラスをシリアル化しますか? それとも、クラスの「シリアル化」メソッドを明示的に探すだけですか (このインスタンスでは見つかりません)?

私はチュートリアルでこの質問に対する答えを見つけることができませんでした.

PS私は失敗がどのように見えるべきかわからないので、「ただ試してみる」ことに消極的です(Boostは単に「何か」をシリアル化しますか?)...

4

2 に答える 2

4

このメソッドは、「gps_position」クラスをシリアル化するために使用できる関数「serialise」を提供しますが、この関数がいったん実行されると、クラス自体がシリアル化可能 (つまり、シリアル化/逆シリアル化に関してプリミティブのように機能する) かどうかはわかりません。作成された場合、またはそのために侵入的な方法を使用する必要がある場合...

はい、クラスは、使用する方法に関係なく、boost.serialization アーカイブで「&」演算子を使用する通常の方法でシリアル化できます。

つまり、たとえば「gps_position」インスタンスのベクトルを含む別のクラスがある場合、Boost は、「gps_position」パラメーターに一致する Boost::serialization 名前空間でオーバーロードされた「serialize」関数を探すことを認識します。親クラスをシリアル化しますか? それとも、クラスの「シリアル化」メソッドを明示的に探すだけですか (このインスタンスでは見つかりません)?

親クラスのシリアル化関数も提供する必要があります。ここでは、子クラスを行ったのとほぼ同じ方法で、クラスの各メンバーをシリアル化します。

PS私は失敗がどのように見えるべきかわからないので、「ただ試してみる」ことに消極的です(Boostは単に「何か」をシリアル化しますか?)...

試してみることが、あなたが学んだ可能性のある最善の方法です。これは、この質問に答えようとしている他の人がドキュメントを簡単に見た後に学んだ方法である可能性が最も高いです。

これは、侵入型と非侵入型の両方のバージョンの非常に簡単なモックアップです。

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <boost/serialization/access.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

// child class serialized using intrusive

struct child
{
  std::string name;

  child() = default;

  explicit child(const std::string& name)
    : name(name)
  { }

  template <class Archive>
  void serialize(Archive& ar, const unsigned int /* version */)
  {
    ar & name;
  }
};


struct parent
{
  std::vector<child> children;

  parent() = default;

  explicit parent(const std::vector<child>& children)
    : children(children)
  { }
};

// parent class serialized using non-instrusive

namespace boost {
namespace serialization {

template <class Archive>
void serialize(Archive& ar, parent& p, const unsigned int /* version */)
{
  ar & p.children;
}

}
}

int main()
{
  parent p1 {{child("one"), child("two"), child("three")}};

  std::stringstream ss;
  boost::archive::text_oarchive oa(ss);
  oa << p1;

  parent p2;
  boost::archive::text_iarchive ia(ss);
  ia >> p2;

  for (auto& child : p2.children) {
    std::cout << child.name << "\n";
  }
}
于 2013-09-18T04:34:01.083 に答える
1

このメソッドは、「gps_position」クラスをシリアル化するために使用できる関数「serialise」を提供しますが、この関数がいったんこの関数を取得すると、クラス自体がシリアル化可能 (つまり、シリアル化/逆シリアル化に関してプリミティブのように機能する) かどうかはわかりません。作成された場合、またはそのために侵入的な方法を使用する必要がある場合...

ドキュメントには次のように記載されています。

次のいずれかが true の場合にのみ、型TSerializableです。

  • プリミティブ型です。[...]
  • これはクラス型であり、以下に詳述するプロトタイプに従って、次のいずれかが宣言されています。
    • クラスメンバー関数serialize
    • グローバル関数serialize
  • Serializable型へのポインタです。
  • Serializable型への参照です。
  • これは、シリアライズ可能な型のネイティブ C++ 配列です。

つまり、たとえば「gps_position」インスタンスのベクトルを含む別のクラスがある場合、Boost は、「gps_position」パラメーターに一致する Boost::serialization 名前空間でオーバーロードされた「serialize」関数を探すことを認識します。親クラスをシリアル化しますか? それとも、クラスの「シリアル化」メソッドを明示的に探すだけですか (このインスタンスでは見つかりません)?

メンバー関数serializeもグローバル関数serializeも定義されていないクラス型 (後者は 2 番目のパラメーターとしてクラス型の非 const ref を持つ) は、シリアライズ可能な概念を満たしません。

ただし、ドキュメントの同じページで:

上記の機能は、すべての STL コンテナーのシリアル化を実装するのに十分です。実際、これは行われており、ライブラリに含まれています。

つまり、適切なヘッダー ファイルをインクルードする<boost/serialization/vector.hpp>と、ベクター テンプレートの特殊化は、それがSerializableである場合にSerializableになります。value_type

あなたのクラスgps_positionSerializableであるため、前述のヘッダーを含めた場合、 astd::vector<gps_position>Serializableです。ただし、そのようなベクトルを含むクラスは、ルールに従って自動的にシリアライズ可能になるわけではありません。メンバーまたは非メンバー関数が必要でしたserialize:

#include <boost/serialization/vector.hpp>
struct gps_position { int i; };
struct gps_path { std::vector<gps_position> v; }

template<class Archive>
void serialize(Archive& ar, gps_position& p, const unsigned int)
{  ar & p.i;  }
// by declaring this function, `gps_position` is Serializable

template<class Archive>
void serialize(Archive& ar, gps_path& p, const unsigned int)
{  ar & p.v;  }
// as `v` is Serializable (because `gps_position` is Serializable),
// you can leave it to the boost library to serialize the individual
// elements of the vector

注: 関数はグローバルである必要はありません。ドキュメントのリンクされたページで説明されているように、非修飾ルックアップと ADL の両方がサポートされています。

移植性を最大限に高めるために、無料の関数テンプレートと定義を namespace に含めますboost::serialization。移植性が問題ではなく、使用されているコンパイラが ADL (Argument Dependent Lookup) をサポートしている場合、無料の関数とテンプレートは次の名前空間のいずれかに置くことができます。

  • boost::serialization
  • アーカイブ クラスの名前空間
  • シリアル化される型の名前空間
于 2013-09-18T04:43:36.493 に答える