1

次のようなテンプレート クラスが与えられます。

template <typename T>
class C
{
T member;
//... some other members that are not of interest here
};

member不要なメモリを占有しないようにするために T として指定できる型はありますか? 最初voidは頭に浮かびましたが、 の変数を宣言できないことは知っていますvoid


もちろん、この例は単純化されています。バックグラウンドは、一部の情報を保持するクラスですが、ユーザーが追加した追加情報を取得できます。ユーザーが追加情報を追加したくない場合は、それらを省略できる必要があります。したがって、基本的に、ユーザーが追加のデータを保存したい場合は作成しますが、C<MyAdditionalData>そうしない場合はC<NoData>データがないようにする必要があります。もちろん、ある種のテンプレートの特殊化を書くこともできますが、すべてを 2 回書くのは好きではありません。

編集
わかりました空のクラスがこれまでに取得できる最も近いものであることがわかりました(アライメントのためにまだ1バイトまたは4/8を消費しています)ので、私の質問は次のとおりです。これは私のコードをより読みやすくするために?

4

5 に答える 5

5

テンプレートクラスをタイプNoDataに特化し、この特殊化でメンバーを定義しないでください。

template <class T>
class C {
   T member;
...
};

template<>
class C<NoData> {
   // Do not declare that member
};
于 2012-04-18T11:39:37.453 に答える
3

これまでのところ、空のクラスが最も近いことがわかったので、私の質問は次のとおりです。コードを読みやすくするために、これに使用する必要がある標準の空のクラスは既にありますか?

いいえ。自分で定義できます。

struct standard_empty_class {};

これを使って。

したがって、基本的に、ユーザーが追加のデータを保存したい場合は作成しますが、C<MyAdditionalData>そうしない場合はC<NoData>データがないようにする必要があります。

私はこれを理解していません。ユーザーがデータを保存したくない場合でも、なぜクラスが必要であり、それでも書く必要があるのC<NoData>でしょうか? その場合は忘れてください。データがないということは、クラスがないことを意味します。それで解決しませんか?

于 2012-04-18T11:20:46.613 に答える
2

ありえないと思います。実際、それは逆です。空のクラスでも、インスタンス化されるとメモリ (1 バイト) を占有するため、インスタンス間でプログラムが異なる可能性があります。あれは

class A {
};

A a, b;  // vars of type A

次にa、 とbは、プログラムがそれらを参照できるように、ある程度のメモリを消費する必要があります。たとえば、if (a == b). メモリを使わないとできません。

于 2012-04-18T11:21:15.797 に答える
2

オブジェクトのサイズが 0 になることはなく、データ メンバーの get-out 句がないため、データ メンバーはありません。

ただし、基本クラスのサブオブジェクトが空の場合、サイズが 0 になることがあります。したがって:

template <typename T>
struct Member {
    T member;
};

template <>
struct Member<void> {
};

template <typename T>
class C : private Member<T>
{
//... some other members that are not of interest here
};

うまくいくはずだと思います。C<void>::memberただし、 が存在しないという事実につまずく可能性があるため、それを使用するメンバー関数はC<void>、コンストラクターを含め、 に対してコンパイルされません。

ユーザーが追加データを保存したい場合は、作成します C<MyAdditionalData>

C追加のデータ メンバーを持たない非テンプレート クラスを用意し、ユーザーがデータ メンバーを追加したい場合はC、基本クラスとして使用してみませんか? 保護されたデストラクタを指定することを忘れないでください。Cすべての基本クラスには、保護されたデストラクタまたは仮想デストラクタのいずれかが必要ですが、Cテンプレート クラスには仮想デストラクタがないため、非テンプレート バージョンも仮想にする必要はありません。

これらの行に沿って、次のことができます。

class CNoData
{
//... some other members that are not of interest here
};

template <typename T>
class CWithData<T> : CNoData
{
T member
// have to duplicate constructors, unfortunately.
};

本当に必要な場合は、型特性を追加します。

template <typename T>
struct C {
     typedef CWithData<T> type;
};

template <>
struct C<void> {
    typedef CNoData type;
};

次に、あなたが書いたところC<MyAdditionalData>に、今、あなたが書きCWithData<MyAdditionalData>、そしてあなたが書いたであろう場所にあなたが書きC<some_type_that_might_be_void>ますtypename C<some_type_that_might_be_void>::type

于 2012-04-18T12:27:43.973 に答える
1

あなたが言ったように、テンプレートにはすでに他のデータが含まれています。仮想メソッドがある場合、それはもう 1 つのメンバーです。

余分なメンバーを追加することは、単純に無視できる非常に小さなオーバーヘッドであるため、C を使用します (または、アライメントよりも小さいメンバーが他にある場合は char も使用します)。

わかりやすくするために typedef を使用します。

typedef C<int> CEmptyGraphNode;
于 2012-04-18T12:04:10.240 に答える