コンパイラ : | g++ (Ubuntu 13.3.0-6ubuntu2~24.04), | 13.3.0 |
OS : | Ubuntu 24.04, | WSL |
従来の列挙型は、列挙型の中で定義されている列挙子が他の名前と衝突してしまう、という問題があります。
例えば、以下のプログラムは名前の衝突が発生してビルドエラーになります。
[コード例(エラー): "enumerator_name_collision.cpp"]
#include <iostream> int main() { int Blue = 1; enum TrafficLight { Blue, Yellow, Red }; // エラー: 'Blue' はすでに定義されています TrafficLight light = Blue; std::cout << "TrafficLight: " << static_cast<int>(light) << std::endl; return 0; }
以下はビルド時の出力です。
"error: ‘Blue’ redeclared as different kind of entity"
というエラー出力を確認することができます。
$ g++ -Wall enumerator_name_collision.cpp -o enumerator_name_collision.out enumerator_name_collision.cpp: In function ‘int main()’: enumerator_name_collision.cpp:5:25: error: ‘Blue’ redeclared as different kind of entity 5 | enum TrafficLight { Blue, Yellow, Red }; // エラー: 'BLUE' はすでに定義されています | ^~~~ enumerator_name_collision.cpp:4:9: note: previous declaration ‘int Blue’ 4 | int Blue = 1; | ^~~~ enumerator_name_collision.cpp:6:26: error: invalid conversion from ‘int’ to ‘main()::TrafficLight’ [-fpermissive] 6 | TrafficLight light = Blue; | ^~~~ | | | int
上記問題を解決するために、スコープ付き列挙型を使用します。スコープ付き列挙型は、"enum struct" または "enum class" を宣言します。
struct と class に違いはありません。
スコープ付き列挙型は、必ず「型名::値」というように必ず型名による修飾が必要です。ただし後述の using 宣言を利用すると、型名の修飾を省略することが可能です。
[コード例(正常): "scoped_enumerator.cpp"]
#include <iostream>
int main() {
int Blue = 1;
enum struct TrafficLight { Blue, Yellow, Red };
TrafficLight light = TrafficLight::Blue;
std::cout << "TrafficLight: " << static_cast<int>(light) << std::endl;
return 0;
}
以下は、ビルドおよび実行時の出力結果です。
正常にビルドすることができ、期待する実行結果を得ることができました。
※ 警告 (warning) が1つ残ってますが、説明の都合上許容させてください。
$ g++ -Wall scoped_enumerator.cpp -o scoped_enumerator.out scoped_enumerator.cpp: In function ‘int main()’: scoped_enumerator.cpp:4:9: warning: unused variable ‘Blue’ [-Wunused-variable] 4 | int Blue = 1; | ^~~~ $ ./scoped_enumerator.out TrafficLight: 0 $
本ページの情報は、特記無い限り下記 MIT ライセンスで提供されます。
2025-09-26 | - | 新規作成 |