2016-12-08 6 views
1

とシリアライザ(簡単にするため、シリアライザは書き込みとデシリアライザは、呼ばれると呼ばれますが、を読む)C++テンプレートや多型

私は許可されていないライブラリを最初からC++ゲーム・シリアライザを書いています。

私が主に気になるのは、読み書きを同期させておくことです(読み込み値は書き込まれた値と同じでなければなりません)。したがって、Packerは両方のタスクを処理し、列挙型で指定されます。

私が持っているどのような私は、私は、これはC++で可能ではないですけど、私は何を探していますがエレガントな方法である

class ElementToSerialize : ISeriablizable { 

    virtual void WriteAndRead(Packer & p) { 
     p.Pack(32); 
     p.Pack("Hello World"); 
    } 
} 

Packer<WRITE> wpacker; 
Packer<READ> rpacker; 
rpacker.buffer = wpacker.buffer; 

WriteAndRead(wpacker); // Will write everything in wpacker.buffer 
WriteAndRead(rpacker); // Will read wpacker.buffer 

を行うことができるようにしたいどのような

enum PackerType { 
    WRITE, 
    READ 
} 

template <PackerType PType> 
class Packer { 
    char *buffer; // Packer will write here 
    uint32_t index; 

    template <typename T> 
    void Pack(T & value); // Calls appropriate functions depending on PType 
} 

この問題に対処する私はすでにタイプ消去を認識していますが、私は解決策のファンではありません。

+0

あなたは 'WriteAndRead'をテンプレートに変更することができます。 –

+1

ここでテンプレートを使用する必要性は必ずしもわかりませんが、作者であろうと読者であろうと、Packerオブジェクトのメンバーに保存して、実行時にそれに応じて動作させることができます。 – Steeve

+0

@appleapple例では指定されていませんが、この関数は仮想関数であると考えられています。私はそれを明確にするために追加します – aguadoe

答えて

2

どのようなもので始まるについて

class IPacker 
{ 
public: 
    virtual void Pack(int& value) = 0; 
    virtual void Pack(float& value) = 0; 
} 

class ISeriablizable 
{ 
public: 
    virtual void Serialize(IPacker & p) = 0; 
} 

class WritePacker : public IPacker 
{ 
    char* buffer; 
    int index = 0; 
public: 
    WritePacker(char* buffer) : buffer(buffer) {} 
    void Pack(int& value) override { /* write to buffer */ } 
    void Pack(float& value) override { /* write to buffer */ } 
} 

class ReadPacker : public IPacker 
{ 
    char* buffer; 
    int index = 0; 
public: 
    ReadPacker(char* buffer) : buffer(buffer) {} 
    void Pack(int& value) override { /* read from buffer */ } 
    void Pack(float& value) override { /* read from buffer */ } 
} 

class ElementToSerialize : public ISeriablizable 
{ 
    int x = 32; 
    std::string y = "Hello world"; 

    void Serialize(IPacker & p) override 
    { 
     p.Pack(x); 
     p.Pack(y); 
    } 
} 
+0

テンプレートをすべてのタイプの完全サポートを保証することを望んでいましたが、私自身。私はそれに行くよ、ありがとう! – aguadoe

+1

IPackerにメソッドを追加できます:virtual Pack(void * data、size_t size)= 0;次に、テンプレートを追加します。 void Pack(T&value){Pack(&value、sizeof(value)); –

+0

しかし...これは、Tが単純なデータ型である場合にのみ機能します。それがstd :: stringや他のデータへのポインタを含む他の型の場合、それはうまくいかないでしょう。 –

1

それは必要条件ではない場合、あなたは完全にテンプレートを使用しないよう、そしてちょうどパッカーは、(一例)readまたはwriteはそうあなたは、実行時にそれを知っているかどうかを格納することができ:

class Packer { 
public: 
    enum Type { 
     READ, 
     WRITE 
    }; 

    char *buffer; // Packer will write here 
    uint32_t index; 
    Type type; 

    Packer(Type t) : type(t) {} 

    void Pack(int& value); 
    void Pack(float& value); 
    void Pack(std::string& value); 
    // etc... 
}; 
+0

これは私が現在使用しているモデルですが、実際にはOO-ishを感じていません。私は本質的に、 'if(type == WRITE)'を行うことなくそれを行うエレガントな方法を探しています。 – aguadoe

関連する問題