Reputation: 4763
A colleague and I bumped into a a weird behavior when working with enums.
We're both compiling the same project, with (presumably) the same make file, with the same compiler (gcc 4.8.4 ) . The only difference would be that I'm an a Linux VM Machine and he's in a native Linux environment but this shouldn't be the source of the issue.
Given the following code snippet
namespace Something
{
enum Something {
DARK_SIDE,
LIGHT_SIDE
}
}
...
Something::Something leEnumVal = Something::Something::DARK_SIDE; // inconsistency here
The inconsistency is that on my computer i get the following error :
'Something::Something' is not a class or namespace
However, everything works fine on in my Colleagues environment.
It's worth while mentioning that we're using QT Creator ,and some extra stuff might be generated in the build process.
Ofc, I managed to make the code compile on my environment, and the inconsistent line became :
Something:Something leEnumVal = Something::DARK_SIDE; // this compiles for both
Q1 : what is the standard way of addressing enum values ?
Q2 : what could generate this inconsistency in the way the compiler treats the code ? (my guess is that my colleague is using some C++ 11 features on his setup, but I need some confirmation before starting to research how he enabled them )
The code used above is used to show the problem we're facing.
Considering that this is a significantly large project, with many enums used, we are facing scenarios where some developers use the first way of addressing enum values while some others are using the 2nd method.
1st method has the benefit of listing during autocomplete solely the values from the qualified enum and not from the entire namespace (such as for the 2nd one).
Considering there are many many enums in the namespace, it makes sense why one would rather go for the first approach.
Upvotes: 3
Views: 504
Reputation: 15290
In C++ prior to C++11, enumerations didn't generate a new namespace for their enumerators (the constants). Your original line of code is not valid in old C++ because there isn't a namespace Something::Something
. This is a good reason to put an enumeration in its own namespace: the alternative and older solution is to put the name of the enumeration in each enumerator, like
enum side {
SIDE_DARK,
SIDE_LIGHT
}
side s = SIDE_DARK;
C++11 introduces scoped enums (a.k.a. strong enums), which work the way your original code wants. To get a full strong enum, you have to ask for it specifically, using enum class
:
enum class side {
DARK,
LIGHT,
}
side s = side::DARK;
But just to be nice, C++11 lets you use the namespace notation when using the enumerator's name, regardless of whether you're using a strong enum or a traditional one. This supports your guess that your colleague has C++11 turned on in his Makefile or compiler options, (e.g. with -std=c++0x
or -std=c++11
).
MSVC (maybe other compilers too) has a non-standard extension allowing you to use the enum as if it were namespaced, even in older C++ versions, so if this were a difference between gcc and MSVC, that would make sense, but you already ruled out that possibility in your question. (I only mention it for future readers.)
As this is a large project, you should set in your coding standard or another project document what version of the language you are targeting. If you're targeting C++11, then you need to update the project's compiler options so that the original code compiles (since it's valid C++11). If you're targeting C++03, anyone who has written code like your first example needs to fix it rather than relying on non-standard options or compiler extensions.
Of course, if you are targeting C++11, and not using strong enums, you have a choice over whether to use the enumeration name as a namespace or not. You may want to specify this in your coding standard, or (better yet) specify that strong enums should be used wherever possible.
Upvotes: 1