2012-07-06 13 views
6

のは、私は最近、プロジェクトのどこかで見つけたコードの構造を見てみましょう:列挙値の衝突

namespace Test 
{ 
    enum EName 
    { 
     CoolEnum, 
     NiceEnum 
    }; 

    enum CoolEnum 
    { 
     CoolVal1, 
     CoolVal2 
    }; 

    enum NiceEnum 
    { 
     NiceVal1, 
     NiceVal2 
    }; 
} 

コンパイラはこのような何かを可能になぜ私の質問です。ここでコードサンプルを取得しましょう:

Test::CoolEnum cEnum = Test::NiceVal1; // INVALID, as compiler refers to Test::CoolEnum value of Test::Ename enum 

なぜこのような混乱が許されますか?なぜ私はenumキーワードを前に付ける必要があるのか​​理解しているので、コンパイラは、同じ名前空間内の他の列挙型の値を使用せず、与えられた列挙型の変数を宣言していることをはっきりと知っています。私はちょうどそのような構造を作ることさえも最初の場所でなぜ理解していない。

+0

Ideoneのコードがエラーを引き起こすため、コンパイラが定義していると思います。http://ideone.com/4GDTF – tinman

+0

だから私はgccを配置しましたが、私が知っている限り、そのような構築は可能です。 –

+0

@Kamil NiceEnumの列挙定数の名前を変更するには、CoolEnumからコピー&ペーストして競合するためです。 –

答えて

7

C++ 11の列挙型クラスは、このためのソリューションです:

namespace Test 
{ 
    enum class EName 
    { 
     CoolEnum, 
     NiceEnum 
    }; 

    enum class CoolEnum 
    { 
     NiceVal1, 
     NiceVal2 
    }; 

    enum class NiceEnum 
    { 
     NiceVal1, 
     NiceVal2 
    }; 
} 

次にあなたがappropiate NiceVal1を使用することができます。

Test::CoolEnum cEnum = Test::CoolEnum::NiceVal1; 

平野の列挙型は、という概念が存在しないC、から継承されました名前空間とは何か?単純な列挙型で何らかの名前空間が導入された場合、列挙型を使用するCコードはまったくコンパイルされません。そのため、後方互換性を損なわないように、enumクラスが導入されました。

+1

知っておいてくださいが、それは与えられた質問に対する答えではありません。私はC++ 11で問題を解決したことをうれしく思っていますが、なぜそれが可能であったのか最初に疑問に思っています。 –

+0

名前空間の外に同じ構造を配置しましたが、それでもC++に対して完全に有効です。 –

+0

私は、あなたが何を指しているのか理解しています。 – mfontanini

1

標準はこの動作を規定しているからです。 3.3.7/2参照:

クラス名(9.1)または列挙名(7.2)は、名前と同じスコープ内で宣言されたオブジェクト、関数、または列挙子の によって隠すことができます。 クラスまたは列挙名とオブジェクト、関数、または列挙子が同じ名前で同じスコープ内(任意の順序)に宣言された の場合は、オブジェクト、関数、または 列挙子名のいずれかの場合は、 クラスまたは列挙名が非表示になります。表示されます。

恐らくこれは、長い時間確立されているCのメカニズム(列挙子が新しい範囲を開かない)との互換性を容易にするためである。

少なくともg ++の場合は、typenameを使用して、列挙子(typename Test::CoolEnum cEnum = Test::NiceVal1;)の代わりに型を使用することを示すことができます。

しかし、一般的には、これらの衝突を完全に防ぐために、別の名前空間またはクラス内のすべての列挙をスコープしたいと思います。

+1

"typename Test :: CoolEnum"は間違っています - GCCはそれを受け入れることになりますが[それを拒否する](http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48920)。代わりに "enum Test :: CoolEnum"を使用してください。 –