2016-08-02 3 views
-1

C++オブジェクトをシリアライズする方法を学習しようとしています。 ここでいくつかの記事を読んだら、boostシリアライゼーション機能を利用し、ロード/セーブ機能を使用してアーカイブするのはいい考えです。しかし、私はブーストライブラリを使用しないでください。フィールドを知らずにC++オブジェクトをシリアライズ

概念的には、フィールドを知らなくてもオブジェクトを保存できますか? C++でのリフレクションがない場合、オブジェクトを格納する唯一の方法は、すべてのクラスメンバーを知ることです。

stringstreamを使用して<<演算子をオーバーロードしてオブジェクトを文字列に変換すると、オブジェクトを直接保存できますか?概念的に

おかげで、K.

+2

いいえ。リフレクションのない言語では、メンバーが何であるかわからない限りメンバーと何もできません。 –

+1

誰かがフィールドを知っている必要があります。呼び出し元がフィールドを知る必要はなく、読み取りと書き込みの両方に1つの機能があるようにすることができます。シリアライゼーションには、バージョニングなどのような厄介な問題がたくさんあることに注意してください。 – Yakk

答えて

1

は、私はそのフィールドを知らなくても、オブジェクトを保存することができます。

いいえ、できません。

C++でのリフレクションがないため、オブジェクトを格納する唯一の方法は、すべてのクラスメンバーを知ることです。

はい。最良の方法は、そのクラス自体にカプセル化されたその知識を残すことである:

class MyClass { 
public: 
    std::ostream& put(std::ostream& os) const { 
     os << field1 << " " << field2 << std::endl; 
     return os; 
    } 
    friend std::ostream& operator<<(std::ostream& os, const MyClass& myclass) { 
     return myClass.put(os); 
    } 
private: 
    int field1; 
    double field2; 
}; 
+0

私はこのデザインが嫌いです。ヘルパーテンプレートを追加して、ioを読み込みバージョンの読み書き機能の1つの関数にすると、物事を改善することができます。 – Yakk

+0

@Yakk間接参照のレベルを追加することはできますが、実際のフィールドがあることを知ることはできません(ここではQED)。 –

+0

これは非常に迅速に複雑になります(クラスが文字列フィールドを持っているかどうかを想像してみてください) - 名前付きメンバごとにヘルパ関数を呼び出すことで 'put'を実装する方が良いと思います。 –

0

あなたが続くことができるのアプローチは、デフォルトでは、タプル-好きで、反復可能オブジェクトをサポートすることです。

は、最初のタプルのような彼らは std::tuple_sizeとADL get<I>サポートするという点である for(:)ループをサポートするタイプ、および種類を検出するために、空想sfinaeを行いread_archiveとwrite_archiveを持っています。

これは、C++での構造化バインディングサポートの1つの形式にも対応しています17。

次に、とto_tie(.)をチェックする、to_tie sfinae adl対応の実装を持ってください。そうで、読み書き可能な場合は、それを使用します。

おそらくどこかにarchive_ioという機能のadl検索が含まれている可能性があるので、あなた自身のioを明示的に書くことができます。

可能な限り自動でアーカイブし、簡単に作成できないものを目標にしています。

関連する問題