Collision of Enum values ​​with enum

Take the code construct that I recently found somewhere in a project:

namespace Test { enum EName { CoolEnum, NiceEnum }; enum CoolEnum { CoolVal1, CoolVal2 }; enum NiceEnum { NiceVal1, NiceVal2 }; } 

My question is why the compiler allows something like this. Take an example code here:

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

Why is such confusion allowed? I understand why I need to add the enum keyword, so the compiler clearly knows that I am declaring a variable of a given enumeration, and not using the value of another enumeration in the same namespace. I just don’t understand why, in the first place, such a design can be made.

+6
source share
2 answers

C ++ 11 enum classes is the solution for this:

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

Then you can use the appropriate NiceVal1 :

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

Ordinary enumerations were inherited from C, where there is no concept of what a namespace is. If simple enumerations have entered some kind of namespace, the C code that uses the enumerations does not compile at all. That's why enum classes were introduced so as not to break compatibility.

+7
source

The answer is that the standard dictates this behavior. See 3.3.7 / 2:

The class name (9.1) or enumeration name (7.2) can be hidden by the name of an object, function, or enumerator declared in the same scope. If the class or name of the enumeration, as well as the object, function or enumerator declared in the same scope (in any order) with the same name, the name of the class or enumeration is hidden wherever the object, function or name of the counter is visible.

Presumably this should facilitate compatibility with the C mechanism (where the enumerator does not open a new area), which has been established over time.

In your case, at least with g ++, you can use typename to indicate that you want to use this type instead of a counter ( typename Test::CoolEnum cEnum = Test::NiceVal1; ).

In general, I like to pop up all the enumerations in a separate namespace or class to completely prevent these collisions.

+1
source

Source: https://habr.com/ru/post/919855/


All Articles