【C++11】スコープ列挙型(Scoped enumerations)
TL;DR
enum class
で定義した列挙型は、従来のenum
に加えて、「整数型への暗黙の型変換を行わない」「列挙型のスコープを持つ」という機能を持つ。
enum class Color { Red, Green, Blue }; // 単にRedと指定するのではなく、どの列挙型に属するのかを指定する Color c = Color::Red; // 明示的な型変換は許可する int color = static_cast<int>(Color::Red); //int color = Color::Red; // コンパイルエラー : 暗黙の型変換はできない
Try it
cpp.sh で試してみた。int
を基底にした場合でも暗黙の型変換は許されないようだ。
enum class Color : int { Red, Green, Blue }; int main() { Color c = Color::Green; // int cc = Color::Blue; // Error: cannot convert 'Color' to 'int' in initialization int cc = static_cast<std::underlying_type<Color>::type>(Color::Blue); return 0; }
Diff
従来の手法との違いとしては、やはり次の2つが大きい。
- 「列挙型のスコープを持つ」
- 「整数型への暗黙の型変換を行わない」
「列挙型のスコープを持つ」に関してはメリットが大きい。
従来の列挙型で同様のスコープを実装したい場合、名前空間を使用して次のように実装していた。 これと比べるとずいぶんスマートになった。
namespace Color { enum enumColor { Red, Green, Blue }; } // namespace Color
一方、「整数型への暗黙の型変換を行わない」については判断が分かれるかと思う。 というのは、整数型への暗黙の型変換を意図的に活用しているケースがあるからだ。
具体的には次のような場合がある。
namespace TableColumn { enum enumTableColumn { Id, Name, Address, numColumn }; } // namespace TableColumn
この列挙型は次の2点で整数型への暗黙の型変換を意図的に活用される。
- 各要素(
Id, Name, Address
)の並びに意味があり、列インデックス(int
)として活用される。 - 末尾の要素(
numColumn
)が列挙子の数(int
)として活用される。
実際にこういう運用は少なくないのでないだろうか。 このように順序に意味がある列挙型を、私は「順序付き列挙型(Enumerations with order)」と呼んでいる(正しい用語があれば教えてください)。
「順序付き列挙型」の場合、スコープ列挙型にしたところで キャストの手間がかかってしまうため、単純には導入できず検討が必要になるだろう。
Column
なお、末尾の要素で列挙子の数を定めることには是非があるようだ。