3

のシリアライゼーション/デシリアライゼーション コードを生成したい

class Object
{
    string a;
    int b;
    long c;
    char d;
};

mpl シーケンスを見て、オブジェクトを識別して取得できるようにする必要があります。メンバーの名前を取得する方法がわかりません。それを知る必要がありますか?

コードは次のようになります

void SerializeObject(ostream os)
{
   serialize(object.a, os);
   serialize(object.b, os);

   //serialize(object.member, os);
}

オブジェクトのレイアウトに対応する mpl シーケンスを定義するだけで上記のコードを生成したいのですが、実行できますか?ヒントを教えてください。

私の目的は:

mpl::vector<String, int, long, char>ユーザーが上記のオブジェクトを定義すると、metaprogram必要なコードを生成できます。

4

3 に答える 3

10

を検討しboost::fusion、マクロBOOST_FUSION_ADAPT_STRUCT()を使用して構造を融合シーケンス(ランダムアクセス)にプロモートします。たとえば、上記の構造を定義すると、次のようなことができます。

BOOST_FUSION_ADAPT_STRUCT(
    Object,
    (std::string, a)
    (int, b)
    (long, c)
    (char, d)
)

for_each昇格されたので、次のように、を使用してメンバーを反復処理できます。

template<typename archive>
struct serializer {
   serializer(archive& ar):ar(ar) {}

   template<typename T>
   void operator()(const T& o) const {
      ar & o;  // assuming binary for example...
   }
   archive& ar;
};

template<typename archive, typename sequence>
void serialize(archive& ar, sequence const& v) {
   boost::fusion::for_each(v, serializer<archive>(ar));
}

使用するには、次のように簡単にする必要があります。

Object foo; // instance to serialize
serialize(<archive>, foo);
于 2011-05-16T22:36:47.270 に答える
2

テンプレートでメンバー名を推測する方法はありません。次のように、すべてを明示的に指定する必要があります。

template<typename ObjT, typename MemberT, MemberT ObjT::*Ptr>
struct member{};

mpl::vector
<
    member<Object, string, &Object::a>,
    member<Object, int, &Object::b>,
    member<Object, long, &Object::c>,
    member<Object, char, &Object::d>
>;

もう 1 つのオプションは、 の生成を支援する関数を作成し、それらを にマージするforをmember定義し、さらに大きな にマージするforを定義することです。型のみを使用しているため、コンパイラは実際の関数呼び出しを最適化できますoperator>>membermember_vecoperator>>member_vecmember_vec

関数は暗黙的なテンプレート引数を使用できるため、シリアライザーが定義するコードを少し減らすことができます。

auto serializer =
        mem(&Object::a) >>
        mem(&Object::b) >>
        mem(&Object::c) >>
        mem(&Object::d);

両方の手法を使用して、自分でシリアライザーを作成しました。2つ目は、私が最も満足していることです。

于 2011-05-16T20:17:01.383 に答える
0

mpl::stringメンバー名を表すために使用できます。私のアプリでは、次のようなコード生成を少し行います。

typedef mpl::string < 'n', 'a', 'm', 'e' > name;

を使用しmpl::c_str < name >::valueて、文字列表現を取得できます。つまり、「名前」。

このようなメンバー名のシーケンス、メンバーポインターの別のシーケンスを保存し、それらを一緒にzipしてから、boost ::fusionクエリアルゴリズムの1つを使用して、特定のメンバー名のメンバーポインターを見つけます。

興味があればコードを投稿します。現在、自宅のPCにあるため、アクセスできません。

于 2011-06-03T05:21:40.557 に答える