enumのスコープ
ブログ始めました。三日坊主にならないといいですね。
一応、コードを載せるときはincludeとstd名前空間、mainのreturnなどは適宜省略していく予定。
そんなわけでタイトル通りenumについて。
enumとは「列挙型」のことで、取り得る値として好きな識別子を設定できる。
enum Fruit { Apple, Banana, Orange, }; // 好きなフルーツは林檎 Fruit like = Apple;
このように、リストメニューのような使い方ができる。
C++のenumはint型とある程度の互換性があり、内部では整数値で表現されている。
通常は上から順に0, 1, 2, ... だが、明示的に値を指定してやることもできる。
enum Fruit { Apple = 1, Banana, Orange = -1, Berry, Grape, }; int main() { cout << Apple << endl; // 1が出力される cout << Banana << endl; // 2が出力される cout << Orange << endl; // -1が出力される cout << Berry << endl; // 0が出力される cout << Grape << endl; // 1が出力される }
AppleとGrapeが同じ値になっているように、複数の項目に同じ値を持たせることも可能だが、中身がAppleかGrapeかどちらなのか識別することはできなくなる。
また、enumにはスコープが無いので名前の衝突が起きることもある。
enum Fruit { Apple, Banana, }; enum Juice { Grape, Apple, }; // Fruit型をJuice型で初期化しようとしているのでエラー! // もしキャストしても、中身は1なのでBananaになる Fruit fruit = Apple;
この問題を避けるために今まで私が使っていた方法が、structのスコープに入れてしまうという方法である。
struct Fruit { enum Type { Apple, Banana, }; }; // 好きなフルーツは林檎 Fruit::Type like = Fruit::Apple;
若干記述が面倒になるが、名前の衝突の問題はなくなり、Appleも何に属しているか一目でわかるようになった。
個人的にはインテリセンスがすっきり見れるのが嬉しい。(Typeも出てしまうけど仕方がない。)
今まではこのように小賢しい記述ですり抜けていたが、今更だが、C++11でenum classが導入されていることを知った。
enum classはそれ単体でスコープを持つことに加え、今までの列挙体よりも強い型付けを持っていることが特徴である。
enum class Fruit { Apple, Banana, }; // 好きなフルーツは林檎 Fruit like = Fruit::Apple; // 今までと違い、int型への暗黙のキャストができないのでコンパイルエラー! int appleNum = Fruit::Apple;
int型へは明示的にキャストしてやれば今までどおり変換することも可能。逆もまたしかり。
このenum classはVisualC++2012から対応しているので、未だに2010を使っているひとは、このためだけに乗り換えてもいいんじゃないかなとも思う。
行番号が出ないのでSyntax Highlighterを導入してやろうとあーだこーだ頑張ったけど、自動リンクの部分まで一緒にコード表示されちゃったりなんだりで挫折した。
Wordpressが使えれば……。