Let's take a code construction that I've recently found somewhere in 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. Let's take a code sample 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 have to prepend enum keyword, so the compiler clearly knows that I'm declaring a variable of given enum, not using value of other enum in the same namespace. I just don't understand why in the first place it's even possible to make such a construction.
C++11's enum classes are 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 appropiate NiceVal1
:
Test::CoolEnum cEnum = Test::CoolEnum::NiceVal1;
Plain enums were inherited from C, where there is no notion of what a namespace is. If plain enums introduced some kind of namespace, C code which uses enums would not compile at all. That's why enum classes were introduced, in order not to break backward compatibility.
The answer is because the standard dictates this behavior. See 3.3.7/2:
A 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 a class or enumeration name and an object, function, or enumerator are declared in the same scope (in any order) with the same name, the class or enumeration name is hidden wherever the object, function, or enumerator name is visible.
Presumably this is to facilitate compatibility with C's mechanism (where an enumerator doesn't open a new scope) which has been established for a long time.
In your case, at least with g++ you can use typename
to indicate you want to use the type instead of the enumerator (typename Test::CoolEnum cEnum = Test::NiceVal1;
).
In general however I like to scope all enumerations in a separate namespace or class to prevent these collisions completely.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With