このエントリーをはてなブックマークに追加

C++11 emum class 入門
Copyright (C) 2015 by Nobuhide Tsuda

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,
	.....
};

演習問題:

参考