C++ の列挙型
この記事では、C++ で列挙型を使用する方法を示します。
C++ でのスコープ外の列挙
列挙はしばらくの間 C 言語の一部でした。C++ も、いくつかの追加機能を備えた同じ概念を実装しました。一般に、列挙は定数整数に名前を付けるメカニズムです。プログラマーは列挙子名を定義します。整数値は、明示的に指定することも、指定された名前の位置から推測することもできます。
列挙型はキーワード enum
を使用して決定され、オプションでタイプの名前を定義できます(例:次のコードスニペットの Color
)。C++ 列挙定数には、実装定義の整数型があることに注意してください。したがって、指定された値が int
よりも大きなスペースを必要とする場合、対応する整数型が基になる型として選択されます。タイプは、列挙名の後にユーザーが明示的に指定することもでき、単一のコロンで区切る必要があります(この記事の 4 番目のコードスニペットに示されています)。
次の例では、Color
という名前の列挙型を定義し、列挙型定数として 6つの色名を指定します。これらの定数には明示的な値が割り当てられていないため、整数値はゼロから始まる位置で推定されます。このコードは、指定された値に制限されている色から文字列への変換関数を実装します。変数 Color
もスコープ外の列挙です。これは、その列挙子(定数)が列挙体自体と同じスコープからアクセスできることを意味します。
#include <iostream>
using std::cout;
using std::endl;
using std::string;
enum Color { RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW };
string ColorToString(Color c) {
switch (c) {
case RED:
return "Red";
case BLUE:
return "Blue";
case GREEN:
return "Green";
case CYAN:
return "Cyan";
case MAGENTA:
return "Magenta";
case YELLOW:
return "Yellow";
default:
return "NAN";
}
}
int main() {
Color col1 = RED;
cout << "the given color is " << ColorToString(col1) << endl;
return EXIT_SUCCESS;
}
出力:
the given color is Red
または、各列挙子が明示的に割り当てられた整数値を持つ列挙型(WeekDay
など)を定義することもできます。この機能を利用して、さまざまな日付規則に従って変更できる柔軟な構造を実装できます。必要に応じて、明示的な値と位置的な値を同じ列挙オブジェクトに混在させることができます。
#include <iostream>
using std::cout;
using std::endl;
enum WeekDay { MON = 1, TUE = 2, WED = 3, THU = 4, FRI = 5, SAT = 6, SUN = 7 };
int main() {
auto today = SAT;
cout << "today is " << today << "th day" << endl;
return EXIT_SUCCESS;
}
出力:
today is 6th day
C++ でのスコープ付き列挙
列挙のもう 1つの便利な機能は、スコープを持つことです。したがって、これはスコープ付き列挙と呼ばれます。後者は、enum class
または enum struct
キーワードを使用して宣言できます。スコープ付き列挙は、スコープの通常の規則に従い、列挙スコープ外ではアクセスできません。プラス面として、グローバルにスコープされた列挙は、スコープされていない列挙のように名前の衝突を引き起こしません。
次のコードサンプルでは、前の例の WeekDay
をスコープ付き列挙として定義しています。スコープのない列挙は、他の変数と同様に cout
関数を使用して出力できますが、スコープのある列挙は、対応する整数値にキャストする必要があることに注意してください。
#include <iostream>
using std::cout;
using std::endl;
enum class WeekDay {
MON = -1,
TUE = 2,
WED = 3,
THU = 4,
FRI = 5,
SAT = 6,
SUN = 7
};
int main() {
auto today = WeekDay::MON;
cout << "today is " << static_cast<unsigned>(today) << "th day" << endl;
return EXIT_SUCCESS;
}
出力:
today is 6th day
スコープのない列挙とは対照的に、スコープのある列挙には名前を付ける必要があります。一方、スコープ付き列挙には、デフォルトの基になる整数型がありません。列挙子が異なる型にキャストされると、基になる型変換によってオーバーフローが発生する可能性があることに注意してください。
#include <iostream>
using std::cout;
using std::endl;
enum class WeekDay : int {
MON = -1,
TUE = 2,
WED = 3,
THU = 4,
FRI = 5,
SAT = 6,
SUN = 7
};
int main() {
auto today = WeekDay::MON;
cout << "today is " << static_cast<unsigned>(today) << "th day" << endl;
return EXIT_SUCCESS;
}
出力:
today is 4294967295th day