26.列挙型
列挙型は名前付け定数ととまったく別なものです。
C++/CLI は二種類の列挙型:標準C++の列挙型(§7.2)と互換である
ネイティブ列挙型(native enums)と、フレームワーク・プログラミングのために用意された
CLI列挙型(CLI enums)をサポートします。
ネイティブ、そして、CLI 列挙型をまとめて
列挙型と称します。
標準 C++(§7.2)で定義されている列挙型は厳密にそのまま同じ意味を持ち続けます。
C++/CLI において、ネイティブ列挙型は次のような拡張を受けます。
public ないし、 private 認識性、背景型の宣言、そして、その列挙型と、ないし、列挙子への属性の配置。
CLI 列挙型は、形成された列挙子の名前が単に名前付けられたCLI列挙型のスコープの中でのみ見え標準 C++ (SS4.5)で定義されている整数促進が適用されない点を除いて、ネイティブ列挙型と同じです。
[例:
public enum Suit : short { Hearts = 1, Spades, Clubs, Diamonds};
は一般にアクセス可能な Suit という名前で、列挙子として Hearts, Spades, Clubs, Diamonds を持ち、その値は1, 2, 3, 4 が期待される、ネイティブ列挙型を定義します。
Suitの背後にある型は short int です。
コード、
enum class Direction { North, South = 10, East, West = 20 };
は、Direction という名前で、North, South, East, West の列挙子を持ち、その値に 0, 10, 11, 20 が期待される、CLI列挙型を定義します。
デフォルトでは Direction の背景となる型は int です。
]
全てのネイティブ配列型と CLI 配列型は System::Enum から暗黙のうちに派生しています。
メタデータは
SS34.13を参照のこと。
26.1 列挙型定義
標準C++(SS 7.2)の成果物である
enum-specifier(列挙指定子)は次のように拡張されます。
enum-specifier:
attributesopt top-level-visibilityopt enum-key identifieropt enum-baseopt
{ enumerator-listopt }
enum-key:
enum
enum#class
enum#struct
enum-specifier(列挙指定子)は enum の
enum-key(その場合、ネイティブ列挙型を定義します)か、enum class ないし、enum struct どちらかの
enum-key(その場合、CLI列挙型を定義します)を含むべきです。
列挙型宣言はオブションとして
attribute(属性)(
SS29)、
top-level-visibility(上層型識別)(
SS12.4)、
enum-base(列挙基本型)(
SS26.1.1)、そして、
enumerator-list(列挙子リスト)のセットを含むことができます。
enum class と enum struct の定義は等価です。
もし、
top-level-visibilityが他のクラスの中にネストしている
enum-specifier 中に含まれている場合、そのプログラムは不正です。
与えられた CLI列挙型の複数定義は、別々に分けられてコンパイルされるソース・ファイル中にあって同じプログラムで使われている場合、同じものとなるべきでしょう。
enum-specifierが enum キーワードを使用した時、その
enum-specifierによって宣言された列挙名とそれぞれの列挙子は即座にその
enum-specifierを含むスコープ中に宣言されます。
enum-specifierが enum class もしくは、 enum struct キーワードを使った時、列挙名はその列挙型自身のスコープ内で宣言されているので、列挙名はスコープ中に宣言されます。
これらの名称は全ての名称に定義されているスコープのルールに従います。
enum 中に value__ と呼ばれる列挙子があるプログラムは不正です。[注意:この名前はメタデータ生成に使われるために予約済みです。]
CLI列挙型定義は
identifier(識別子) を省略するべきではありません。[注意:CLI列挙型の列挙子はその親の列挙名を通してのみアクセスすることができる。そのような名前のないCLI列挙型は使えません。]
26.1.1 列挙型基本仕様
標準 C++ 中にあるのと同様に、それぞれの列挙型は、列挙型に定義された全ての列挙子値を表現することができる背景型に対応しています。しかしながら、標準 C++ と異なり、C++/CLI は
enum-base を通して背景型の指定を許しています。
enum-base:
: type-specifier-seq
列挙型の背景型は次のもののどれか一つであると明示的に宣言することができます:System::Boolean, System::Byte, System::SByte, System::Int16, System::UInt16, System::Int32, System::UInt32, System::Int64, System::UInt64、ないし、これらにマップされる任意のプリミティブ型の一つ。
もし、ネイティブ列挙型に背景型が指定されていない場合には、標準 C++(SS7.2)のルールが宛われます。もし、CLI列挙型に背景型が与えられていない場合には、 int の背景型を持ちます。
26.1.2 初期列挙子値
列挙型の列挙子の背景型
enum-base が bool 型であれば、それぞれの要素を明示的に初期化するべきです。
もし、列挙型の
enum-base が bool より上の任意の整数型である場合、列挙子に代入される値は明示的、暗黙的に標準 C++ で定義されたものと同様になります。
26.1.3 CLI列挙型の値と演算子
それぞれのCLI列挙型毎に違う型として定義されます。
明示的な列挙子変換が、CLI列挙型と整数型間、CLI列挙型とCLI列挙型間の変換に必要です。
CLI列挙型が取ることのできる値のセットはそのenumメンバに制限されません。
特に、列挙型の背景型の任意の値は列挙型にキャストすることができ、その列挙型の異なる正常な値となります。
CLI列挙子は自身を含んでいる列挙型の型を(他の列挙子の初期化中を除いて)持っています。
値 v に関連づけられた列挙型 E で宣言された列挙子の値は、static_cast<E>(v) です。
次の演算子はCLI列挙型の値でも使うことができます。
==, !=, <, >, <=, >=, +, -, ^, &, |, ~, ++, --, sizeof。
26.2 System::Flags 属性
CLI列挙型が与えられた時、この属性は基底型(System::Enum)のメソッドのいくつかの振る舞いにおいて、特に、列挙型がビット・フィールドとして複数の値を保持するのに使われるようなインスタンスの時に、変化します。[例:次のように列挙型が与えられた場合、
[Flags] public enum class StatusBits { A = 1, B = 2, C = 4 };
StatusBits sb = StatusBits::B;
Console::Writeline("sb = {0}", sb);
sb = StatusBits::A | StatusBits::B | StatusBits::C;
Console::Writeline("sb = {0}", sb);
その出力は、
sb = B
sb = A, B, C
しかしながら、その属性が除かれた場合には、出力は
sb = B
sb = 7
と、Enum::ToString の振る舞いが変わります。]