【列挙型⇔数値型】enumとint型を相互変換する方法と内部型への数値変換

C++の場合、列挙型と整数型間の変換には明示的な型変換が必要です。ここでは両型の変換方法を解説します。またenumの正確な内部型を取得してより厳格な変換を行う方法も紹介します。

目次

列挙型から数値型への変換(enum to int)

C++の列挙体(enum class)は暗黙の型変換には対応していません。そのため、明示的なキャスト処理が必要です。

enum class Enum { A, B, C };
int i = 0;

i = static_cast<int>(Enum::A);
i = (int)Enum::B;
i = int(Enum::C);

static_castによる型キャストが一般的です。C言語スタイルのキャスト((Type)value)はC言語ソースとの互換性を意識する際に使うとよいでしょう。3つめの関数呼び出し形式のキャスト(Type(value))は、基本的にCスタイルキャストと同等の働きをします。

なおC言語由来の列挙体については、暗黙の型変換が効くため、キャスト処理は不要です。

enum Enum { A, B, C };
int i = Enum::A;

数値型から列挙型への変換(int to enum)

C++の列挙体もC言語由来の列挙体も、いずれも明示的な型変換が必要です。

enum Enum { A, B, C };
Enum e = Enum::A;

e = static_cast<Enum>(1);
e = (Enum)2;
e = Enum(3);

C++の世界ではstatic_castの利用が推奨されています。各キャストの意味は先程のenum to intの節が参考になります。

列挙体の内部型を取得してより安全に数値変換する

underlying_typeテンプレートクラスで列挙体の内部型(基底型)を取得できます。これによって正確な精度による厳密な型変換が実現できます。

// #include <type_traits> // underlying_type
enum class Enum : int64_t { A, B, C };

typename std::underlying_type<Enum>::type i = static_cast<std::underlying_type<Enum>::type>(Enum::A);
// int64_t j = static_cast<int64_t>(Enum::A); // 同等処理

sizeof(i); // 8 (8byte/64bit)

C言語由来のenum型の場合も同様に内部型が取得が可能です。なおstd::underlying_type_t<T>typename std::underlying_type<T>::typeの短縮版で、C++14以降のコンパイラで利用可能です。

enum G { GG = LONG_MAX };
sizeof(std::underlying_type_t<G>); // 8
sizeof(long);                      // 8

enum H {};
sizeof(std::underlying_type_t<H>); // 4
sizeof(int);                       // 4

enum型では、基底型の省略時に適切な基底型が自動的に割り当てられますが、その際型は列挙定数の値によって動的に決定されるという特徴があります。基本はint型が指定されますが、列挙定数の内部値がint型の範囲を超えると、long型が指定される場合もあります。underlying_typeはそのような動的な型を取得する目的にも利用できますので覚えておくと良いでしょう。

C++は型付けが強いため暗黙の変換が行われない点に注意

C++のスコープ付きの列挙型(scoped enum)は強く型付けされているため、数値型から列挙型への暗黙的な変換には対応していません。これはC言語由来のenumでも同様です。

enum class Enum { A, B, C };
Enum e = 1; // Cannot initialize a variable of type 'Enum' with an rvalue of type 'int'
e = 1;      // Assigning to 'Enum' from incompatible type 'int'

また列挙体から数値型への変換については、Cスタイルのenumでは暗黙の型変換が行われますが、C++のスコープ付きのenumでは行われません。

enum class Enum { A, B, C };
int i = Enum::A; // Cannot initialize a variable of type 'int' with an rvalue of type 'Enum'
広告