Objective-CのEnum
標準C++03ではenumの構文が拡張され、標準C++11では更に、scoped enumerationがサポートされたそうだ。
C++11のEnum 参考:
http://d.hatena.ne.jp/spinor/20110918/1316321563
Cのenumとの主な違いは、
・enum型の前方宣言が可能
・名前空間を汚さずに、identifier::nameで参照する
・整数型との変換に明示的キャストが必要
// 前方参照 enum class Signal : unsigned; struct Foo { // 前方参照したから、変数宣言できる Signal s; }; // 列挙定義 enum class Signal : unsigned { RED = 1, BLUE, YELLOW }; // RED, BLUE, YELLOWは列挙型Signalの名前空間内の定数なので、名前衝突しない static const int RED = 1; void some_function() { Foo f; // 列挙値の参照は、identifier::nameの形式で行う f.s = Signal::BLUE; }
Objective-Cでは、NS_ENUMマクロを使う。
typedef NS_ENUM(NSInteger, Signal) { kSignalRed = 1, kSignalBlue, kSignalYellow };
NS_ENUMマクロは、コンパイル環境に応じて、サポートされている形式のenumを定義するらしい。
要するに下位互換目的。
Xcode 5.1で試したところ、.mm ファイルでコンパイルした場合、scoped enumerationとしてコンパイルされた。.m ファイルでコンパイルした場合は、unscoped enumerationとしてコンパイルされた。どちらでも前方宣言は可能だった。
NS_ENUMマクロを使うからには、基本的には、列挙値をidentifier::name形式で参照すべきではないだろう。
もっとも、iOS, OS X環境以外でObjective-Cを使うことなんてほとんどないだろうし、通常、Xcode以外で開発することもそうないだろうから、NS_ENUMの恩恵というのは、ほとんど感じられる機会はないのではなかろうか。ぜいぜい、Cのenumを直接使うよりは、幾分マシか、といったところだろう。
ちなみに、定数名を k で始めるのは、ドイツ語 konstant から来ているそうな。
このkで始める命名習慣はObjective-Cでしか見たことがないので、CやC++のプロジェクトで使うべきではないだろう。下手をすると、あなたのXcode.appへのリンクがEmacsに置き換えられてしまうという嫌がらせを受けるかもしれない。