web-dev-qa-db-ja.com

(方法)列挙型のアイテムをカウントできますか?

この質問は、私が

enum Folders {FA, FB, FC};

そして、各フォルダにコンテナの配列を作成したかった:

ContainerClass*m_containers[3];
....
m_containers[FA] = ...; // etc.

(マップを使用すると、はるかにエレガントになります:std::map<Folders, ContainerClass*> m_containers;

しかし、元の質問に戻ると、配列サイズをハードコーディングしたくない場合、Foldersにあるアイテムの数を把握する方法はありますか? (たとえば、FCがリストの最後の項目であり、ContainerClass*m_containers[FC+1]私が間違っていなければ。

89
fuenfundachtzig

これを行うには本当に良い方法はありません。通常、enumに余分な項目が表示されます。

enum foobar {foo, bar, baz, quz, FOOBAR_NR_ITEMS};

そのため、次のことができます。

int fuz[FOOBAR_NR_ITEMS];

まだあまり素敵ではありません。

しかし、もちろん、列挙型のアイテムの数だけでは安全ではないことを理解しています。

enum foobar {foo, bar = 5, baz, quz = 20};

アイテムの数は4になりますが、列挙値の整数値は配列インデックスの範囲外になります。配列のインデックス付けに列挙値を使用することは安全ではありません。他のオプションを検討する必要があります。

編集:要求に応じて、特別なエントリをもっと突き出させました。

114
wich

C++には、さまざまな type-safe列挙テクニック があり、それらの一部(たとえば、提案されたが、決して提出されていない Boost.Enum )の取得のサポートが含まれています列挙のサイズ。

CおよびC++で機能する最も単純なアプローチは、列挙型ごとに... MAX値を宣言する規則を採用することです。

enum Folders { FA, FB, FC, Folders_MAX = FC };
ContainerClass *m_containers[Folders_MAX + 1];
....
m_containers[FA] = ...; // etc.

Edit{ FA, FB, FC, Folders_MAX = FC}{FA, FB, FC, Folders_MAX]に関して:... MAX値を列挙の最後の正当な値に設定することを好みますいくつかの理由で:

  1. 定数の名前は技術的に正確です(Folders_MAXが最大の列挙値を提供するため)。
  2. 個人的には、Folders_MAX = FCが他のエントリと比べてもう少し際立っているように感じます(最大値を更新せずに誤って列挙値を追加することは少し難しくなります)。
  3. GCCには、次のようなコードに対する「スイッチに含まれない列挙値」などの有用な警告が含まれています。 Folders_MAX == FC + 1にすると、スイッチに含まれてはならない... MAX列挙値が大量に発生するため、これらの警告は中断されます。
 switch(folder)
 {
 case FA:...; 
 case FB:...; 
 //おっと、FCを忘れた!
} 
32
Josh Kelley

STL形式での特性はどうですか?例えば:

enum Foo
{
    Bar,
    Baz
};

書きます

std::numeric_limits<enum Foo>::max()

特殊化(c ++ 11を使用している場合はconstexprである可能性があります)。次に、テストコードで静的アサーションを提供して、std :: numeric_limits :: max()= last_itemという制約を維持します。

7
Wojciech Migda

Folders_MAXまたは同様の名前のエントリを列挙の最後に追加し、配列を初期化するときにこの値を使用します。

ContainerClass* m_containers[Folders_MAX];
3
Kevin Doyon

関数への引数として列挙型を使用するのが好きです。 「オプション」の固定リストを提供する簡単な手段です。ここでの上位の回答の問題は、それを使用して、クライアントが「無効なオプション」を指定できることです。スピンオフとして、基本的に同じことを行うことをお勧めしますが、enumの外で定数intを使用してそれらのカウントを定義します。

enum foobar { foo, bar, baz, quz };
const int FOOBAR_NR_ITEMS=4;

それは快適ではありませんが、定数を更新せずに列挙型を変更しない場合、きれいな解決策です。

2
BuvinJ

C++の列挙で値の数を実際に取得する方法はありません。前述のソリューションは、配列を大きくしたり、小さくしたりする状況に陥る可能性がある値を定義する場合、列挙値を定義しない限り機能します。

enum example{ test1 = -2, test2 = -1, test3 = 0, test4 = 1, test5 = 2 }

この例については、5つのアイテムの配列が必要な場合、結果は3つのアイテムの配列を作成します

enum example2{ test1 , test2 , test3 , test4 , test5 = 301 }

この例については、5つのアイテムの配列が必要な場合、結果は301アイテムの配列を作成します

一般的なケースでこの問題を解決する最善の方法は、列挙を反復することですが、それは私が知っている限りではまだ標準ではありません

1
user4425844