C++11 enum class とは
enum class とは、これまでいくつかの問題があった enum を改良したものだぞ。
従来の enum にもそれなりに便利な点があるので、それはそれで残しておき、構文を少し追加することで、新しく安全な enum を提供している。
enum Enum1 { BLACK = 1, WHITE, }; と宣言すると、BLACK, WHITE の値をもつ型の様な Enum1 が出来る。
しかし、BLACK, WHITE という識別子は、この型名のスコープ内固有というわけではなく、以下の様にスコープ名を省略することが出来てしまう。
enum Enum1 { BLACK = 1, WHITE, }; Enum1 e1 = BLACK;
そのために、同じ列挙子名を異なる enum で使用することが出来ない。
enum Enum1 { BLACK = 1, WHITE, }; enum Enum2 { BLACK = 1, WHITE, }; // コンパイルエラーとなる(VS2013)
これでは、ENUM1_BLACK, ENUM2_BLACK の様に enum ごとに列挙子名を変える必要があり、とても不便である。
また、enum は型としては不完全で、整数として扱われ、int 型への代入が出来てしまう。
enum Enum1 { BLACK = 1, WHITE, }; int e = BLCAK; // int 型に代入してもエラーにならない
これは無名の enum を連続する値を持つ定数群の宣言に使いたい時に便利なのだが、型安全ではなく危険なコードの元になってしまうことがある。
それらの問題を解決するために、C++11 で導入されたのが enum class (または enum struct)だ。 過去の互換性のために、従来の enum はそっくりそのまま残っているので、古いソースもそのまま使え、 新しいコードを書く場合は enum class を使い、より安全なコードを書くことが出来る。
宣言方法
「enum class スコープ名 { 列挙子... };」または「enum struct スコープ名 { 列挙子... };」
スコープ名は省略出来ない。
列挙子... の部分はこれまでの enum と同じ
スコープ名が型名となる。
enum class BoadItem { SPACE = 0, BLACK, // 1 WHITE, // 2 }; BoadItem v; // SPACE または BLACK または WHITE を値として持つ変数宣言
列挙子を参照するときは、スコープ名::列挙子 と記述する。スコープ名は省略出来ない。
BoadItem v = BoadItem::SPACE;
これまでは名前の衝突を避けるために、BOARD_ITEM_SPACE の様にプレフィックスを付けることがあったが、 enum class を使えば、よりスマートに名前の衝突を避けることができる。
参考までに、以前であれば以下のように書いた。
enum BoadItem { BOARD_ITEM_SPACE= 0, BOARD_ITEM_BLACK, // 1 BOARD_ITEM_WHITE, // 2 }; BoadItem v = BOARD_ITEM_SPACE;
これまでの enum は整数として扱われていたので、以下の様な記述が可能で、型安全ではなく危険性があった。
enum { SPACE = 0, BLACK, // 1 WHITE, // 2 }; int v = SPACE; // 整数型へ代入できてしまう
しかし、enum class であれば、ちゃんとコンパイルエラーが発生するので、危険なコードを自動的に避けることが出来る。
enum class BoadItem { SPACE = 0, BLACK, // 1 WHITE, // 2 }; int v = SPACE; // コンパイルエラーとなる
「enum class 識別子 : 型 { 列挙子 };」で、型を明示的に指定できる。
省略した場合は int となる。
列挙型が構造体要素の場合に、型を uchar などにしメモリを節約することも出来るぞ。
enum class Enum1 : unsigned char { VALUE0 = 0, VALUE1, ..... };
演習問題: