2012-03-19 4 views
1

私はNOPか状態を持つことができる属性の束を持っています。それらの要件は、ユーザーが属性を必要としないときにサイズを持たないことですが、依然として特定のメソッドを含んでいます。例:コンパイル時にメンバーを作成する

struct AttributeATag {}; 

/* The template used when AttributeATag is not specified */ 
template <typename T> 
class AttributeA 
{ 
public: 
    void foo(uint32_t v) 
    { 
     // Nop, do nothing 
    } 

    enum 
    { 
     HasAttributeA = false 
    }; 
}; 

/* The template specialization used when AttributeATag is specified */ 
template <> 
class AttributeA<AttributeATag> 
{ 
public: 
    void foo(uint32_t v) 
    { 
     this->omgVariable = v; 
    } 

    enum 
    { 
     HasAttributeA = true 
    }; 
protected: 
    int omgVariable; 
}; 

template <typename ATag> 
class MyUberClass : public AttributeA<ATag> 
{ 
    // This class now has omgVariable or not, depending on ATag and it 
    // has either a NOP method or one which actually does something 
    void doSomething() 
    { 
     if (AttributeA<ATag>::HasAttributeA) 
     { 
      /* ... */ 
     } 
    } 
}; 

これは動作しますが、今問題がある:NOPの大きさは、属性、空のクラスでありながら、100の空の属性はMyUberClassに未使用のスペースの多くを追加することを意味し、0ではありません。

テンプレートパラメータに基づいてメンバー変数を追加/削除する方法はありますか?


編集:私は次のことをしようとすると

私の知る限りでは、空のクラスは0の大きさを持っていない、私ははsizeof(B)== 4

template <typename T> 
class A 
{ 

}; 

class B : public A<int>, public A<double>, public A<char>, public A<long>, public A<bool> 
{ 

}; 
を取得しますこのテストで
+0

'AttributeA 'は 'ATag = AttributeTag'の場合にのみサイズを持ちます。ケースの残りの部分は空のクラスのみになります。また、この「100」番号はどこから来るのでしょうか?私は何の問題も見ません。ご質問を明確にしてください。 – iammilind

+0

100は、問題を誇張して作られています。 – Howie

答えて

0

基本クラスとしてAttributeAを使用しているので、ほとんどすべてのコンパイラは、空の基本クラスを使用して、空の基本クラスが子クラス内にスペースを使用しないようにしますクラスはゼロ以外です。私はここに問題があるとは思わない。

すべてのクラス(base/children)は、少なくとも1バイト(コンパイラがすべてを埋める場合は4つ)を取る必要がありますが、空のベース(ほとんどの場合)は子クラスのサイズをすでにされていたでしょう。

+0

私はMSVC 10を使って私のEDIT(私のポストを参照)を走らせました。そして、sizeof(B)はまだリリースでコンパイルするときに4を返します。これが最適化されていると確信していますか? – Howie

+0

これは私のコンパイラの問題だと思います。それは空の基底クラスの最適化を適用する必要がありますが、何らかの理由でMSVC10は最初の基本クラスに対してのみ行い、他のクラスには1バイトを追加します。 – Howie

0

:あなたはまだかかわらずにとして、それへのポインタを持ってできるようにする必要がありますので、gccの上

#include <iostream> 
struct g{}; 
int main() 
{ 
    std::cout << sizeof(g) << std::endl; 
} 

私は1のサイズを取得するには、これはおそらくですそれが状態を保持しているかどうか。

私はクラス以外のものに頼らずに、その周りが遠く離れていません。

+0

クラス以外のものはありますか?それは何ですか? – Howie

+0

@HowieHowitzer私の答えがどこで終わるか私は恐れている。たぶん別のデザインかもしれませんが、それはすべて役に立つとは限りません。 – 111111

0

空のクラスは、(空の)クラスが継承されているかどうかに関係なく、1バイトの最小サイズを持ちます。
あなたの例では、class Bは、他のクラスから継承しても継承しなくても、最小限の実装定義サイズ(あなたの場合は4バイトと思われます)を持ちます。

これは、空のclassオブジェクトが一意のアドレスを持つことができるようにするために必要です。それについては何もできません。

+0

これはsizeof(A )== 1ではありません。つまり、空のクラスは私のコンパイラ(MSVC10)を使用して1バイトのサイズを持つので、sizeof(B)== 4の場合、空のクラスは確かにBのサイズに加算されます。 – Howie

関連する問題