2

yaml-cppを使用してある種のシリアル化を行っています。これを機能させるには、各クラスでシグネチャを使用してメソッドを宣言する必要があります。

template <typename T> void Serialize(T& s);

これTは、保存時と読み込み時の別のクラスです。2 つのクラスのインターフェイスは同じですが、ほとんどのメソッドがテンプレートであるため、抽象基本クラスを作成できません。この部分は正常に動作しています。私はそれを と で接続しようとYAML::Nodeoperator>>ましYAML::Emitteroperator<<

についてoperator<<は、非常に残酷ではありますが、実用的な解決策があります。まず、シリアライズ可能なすべてのクラスのスーパークラスを宣言します。

template <typename T> class Serializable {};

次に、次を使用できますoperator<<

template <typename T>
YAML::Emitter& operator<<(YAML::Emitter& out,
                          Serializable<T>& val)
{
    Serializer serializer(out);
    reinterpret_cast<T*>(&val)->Serialize(serializer);
    return out;
}

これreinterpret_castはかなり恐ろしく見えますが、今のところ機能しており、合法であるかどうかさえわかりません. についても同じことを試みましたが、うまくいきませoperator>>んでした。次のようになります。

template <typename T>
void operator>>(const YAML::Node& node,
                Serializable<T>& val)
{
    Deserializer deserializer(node);
    reinterpret_cast<T*>(&val)->Serialize(deserializer);
}

しかし、gcc (4.6.2) と clang(2.9) はどちらもそれを無視し、operator>>nodeimp.h (yaml-cpp の一部) で定義されたものを使用します。

template <typename T>
inline void operator >> (const Node& node, T& value) {
    if(!ConvertScalar(node, value))
        throw InvalidScalar(node.m_mark);
}

私の質問は次のとおりです。これをどのように解決すればよいですか?私が絶対に望んでいるのは、シリアライゼーションとデシリアライゼーションの両方に 1 つのメソッドだけを用意し、yaml-cpp でサポートされている通常の型のように >> と << を使用できるようにすることです。

4

1 に答える 1

0

まず、約reinterpret_cast:あなたが実際に欲しいstatic_cast。あなたの場合、それが(単なる a ではない)であることを知っているval のでT、直接Serializable<T>キャストできます。

ここでは、クラスを次のように宣言していると仮定しています

class Foo: public Serializable<Foo> { ... };

reinterpret_castのバイトvalとして解釈しますが、これは動作することが保証されていませんが、単一の継承があり、メンバー変数を追加しないTため、おそらく動作します。Serializable<T>

次に、実際の問題について説明します。これは yaml-cpp のバグであり、現在は修正されています ( mercurial リポジトリを使用している場合はr52790a15757dを参照してください。http: //code.google.com/p/yaml- cpp/issues/detail?id=126私が開いた課題の場合)。

上記の修正により、コードが機能するはずです。リポジトリに追いついていない場合、差分はかなり小さいです。yaml-cpp のバージョンにパッチを当てることができます。

于 2011-11-01T22:26:06.077 に答える