2011-01-27 5 views
0
template<typename T> 
class MyClass 
{ 
...... 
private: 
    union u_ 
    { 
     struct m_ 
     { 
      int i1; 
      int i2; 
      int i3; 
     } m; 
     char data[SIZE]; // convenience buffer for serialization/deserialization; 
    } u; 
    T container; 
...... 
}; 

MyClassのオブジェクトをシリアライズ/デシリアライズできるように、私はデータフィールドを結合するためにユニオンを使用し、データバッファを使用して卸売りします。私はデータが誰かの将来の拡張のためにデータメンバーのコレクションのために十分に大きいことを確認したいので、私はこの静的なアサートを追加しました。実際のテンプレートパラメータを指定せずにstatic_assertできますか?

static_assert(sizeof(MyClass<int>::u_::data) >= sizeof(MyClass<int>::u_::m_)); 

このアプローチには2つの問題があります。まず、コンパイラーは、共用体が公開されていないと不平を言う。第2に、これは任意のコンテナ型Tに当てはまるはずですので、具体的にする必要はありませんが、intをダミー型として与えることはできませんが、静的なアサートのためだけに別の型を導入したくありませんここにダミータイプを使用する方法はありますか?

もっと洗練されたソリューションはありますか?

EDIT:James、移植性の問題を提起してくれてありがとう。エンディアンとアライメントは正当な問題ですが、私の場合はシリアル化/逆シリアル化がローカルで行われるため、問題ありません。

答えて

1

さらに洗練されたソリューションがありますか?

構造体をcharの配列として再解析するだけではどうですか?

struct m_ 
{ 
    int i1; 
    int i2; 
    int i3; 
}; 

// ... 
m_ m; 
char* data = static_cast<char*>(static_cast<void*>(&m)); 

すべてのオブジェクトは安全にcharの配列として再解釈できます。もちろん、整列、パディング、データ型のサイズ、潜在的なエンディアンやその他の表現の問題については心配する必要がありますが、おそらく、シリアライズ実装を書いているので分かっているはずです。これに代えて

+3

パディングの可能性があるため、これは非常に悪い考えです。コンパイラは構造体メンバの間にバイトを自由に挿入でき、実行時には完全に未定義です。 –

+1

このようにシリアル化を行うことは非常に悪い考えです。しかし、問題の元のコードはすべて同じ問題を抱えていますが、これは少なくともわずかな改善です。 –

+0

@axel:trueですが、この回答は元の質問と同じ精神です。同じタイプ(つまりレイアウト)の2つの構造体のオッズを追加しますが、異なるパディングは私にとってはほとんどスリムに見えます。 – flownt

1
char data[SIZE]; 

、あなたはこれを行うことができます。

static_assert(sizeof(MyClass<int>::u_::data) >= sizeof(MyClass<int>::u_::m_)); 

それは常に満足しますので、どんなに:

char data[sizeof(m_)]; 

それは、常にこのstatic_assertに条件を満たしますあなたはではなく、でもstatic_assertを書く必要があります!

+0

あなたが言ったことは真実です。ありがとう。 – grokus

+0

@grokus:問題が解決した場合は、「受け入れられた答え」にあなたの質問をマークしてください。 – Nawaz

0

privateの問題を解決するには、たとえばコンストラクタや静的メソッドのように、static_assertをクラスの内側に配置することを検討してください。

関連する問題