namespaces for enum types - best practices
Original C++03 answer:
The benefit from a namespace
(over a class
) is that you can use using
declarations when you want.
The problem with using a namespace
is that namespaces can be expanded elsewhere in the code. In a large project, you would not be guaranteed that two distinct enums don't both think they are called eFeelings
For simpler-looking code, I use a struct
, as you presumably want the contents to be public.
If you're doing any of these practices, you are ahead of the curve and probably don't need to scrutinize this further.
Newer, C++11 advice:
If you are using C++11 or later, enum class
will implicitly scope the enum values within the enum's name.
With enum class
you will lose implicit conversions and comparisons to integer types, but in practice that may help you discover ambiguous or buggy code.
Namespace level enums in c++
With C++11
This answer was originally written in 2011. Now that C++11 support is widely available, the preferred way is to use enum class
, as Matthew D. Scholefield points out below:
enum class Player {
User,
Computer
};
The enumerated constants must be qualified with the name of the enum when referenced (e.g., Player::Computer
).
Before C++11
No, there's nothing inherently wrong with an enum being public. Bear in mind, however, that enumerated constants cannot be qualified with the name of the enclosing enum type. That is, you cannot write Player::USER
or similar to refer to the USER
constant; they appear directly in the enclosing namespace. As such, it might be a good idea to set a prefix for your constants so that no name collisions occur.
For instance, consider the following declaration:
enum Player {
PL_USER,
PL_COMPUTER
}
This is safer, because name collisions are much less likely with the "PL_" prefix. Additionally, it improves code readability by hinting at which enum a given constant belongs to.
Languages like C# and Java have adopted a slightly different approach to enums, where one has to specify both the name of the enumeration and the name of the constant, such as Player.USER
. A similar effect can be achieved in C++ by embedding the enum declaration within a namespace of its own. For example:
namespace Player {
enum Type {
USER,
COMPUTER
}
}
This has the effect of embedding PLAYER
and COMPUTER
in the Player
namespace instead of the global (or otherwise enclosing) namespace. Whether this is a good approach or not is, in my opinion, a matter of preference.
enum in a namespace
I personally don't like the second variation because the status_
part seems redundant to me. The former version avoids that problem, but having a type status::status
looks strange too. Furthermore, a namespace is open to modification, so in case somebody did something like
namespace status {
void error( const char *msg );
}
You would get a compiler error since the function error
clashes with your enum
value.
I prefer to use a third variation:
struct MouseButton {
enum Value {
Left, Middle, Right
};
};
This lets me write functions like
void handleMouseButton( MouseButton::Value b ) {
switch ( b ) {
case MouseButton::Left: // ...
case MouseButton::Middle: // ...
case MouseButton::Right: // ...
}
}
Equivalent of using namespace X for scoped enumerations?
So, is there a way to avoid having to type
CatState::
all the time?
Not before C++20. Just as there's no equivalent for having to type ClassName::
for static class members. You can't say using typename ClassName
and then get at the internals. The same goes for strongly typed enum
s.
C++20 adds the using enum X
syntax, which does what it looks like.
You can of course not use enum class
syntax, just using regular enum
s. But then you lose strong typing.
It should be noted that one of the reasons for using ALL_CAPS for weakly typed enums was to avoid name conflicts. Once we have full scoping and strong typing, the name of an enum is uniquely identified and cannot conflict with other names. Being able to bring those names into namespace scope would reintroduce this problem. So you would likely want to use ALL_CAPS again to help disambiguate the names.
Where is the best place to locate enum types?
Why treat enums differently to other types? Keep them in the same namespace as they're likely to be used - and assuming they're going to be used by other classes, make them top-level types in their own files.
The only type of type which I do commonly clump together is delegates - I sometimes have a Delegates.cs file with a bunch of delegates in. Less so with .NET 3.5 and Func/Action, mind you.
What's the best practice to code shared enums between classes
The best practice is creating separate file for each class, enum, or other type.
MyEnum.cs
namespace Foo
{
public enum MyEnum
{
High,
Low
}
}
Class1.cs
namespace Foo
{
public class Class1
{
public MyEnum MyProperty { get; set; }
}
}
Why is enum class preferred over plain enum?
C++ has two kinds of enum
:
enum class
es- Plain
enum
s
Here are a couple of examples on how to declare them:
enum class Color { red, green, blue }; // enum class
enum Animal { dog, cat, bird, human }; // plain enum
What is the difference between the two?
enum class
es - enumerator names are local to the enum and their values do not implicitly convert to other types (like anotherenum
orint
)Plain
enum
s - where enumerator names are in the same scope as the enum and their
values implicitly convert to integers and other types
Example:
enum Color { red, green, blue }; // plain enum
enum Card { red_card, green_card, yellow_card }; // another plain enum
enum class Animal { dog, deer, cat, bird, human }; // enum class
enum class Mammal { kangaroo, deer, human }; // another enum class
void fun() {
// examples of bad use of plain enums:
Color color = Color::red;
Card card = Card::green_card;
int num = color; // no problem
if (color == Card::red_card) // no problem (bad)
cout << "bad" << endl;
if (card == Color::green) // no problem (bad)
cout << "bad" << endl;
// examples of good use of enum classes (safe)
Animal a = Animal::deer;
Mammal m = Mammal::deer;
int num2 = a; // error
if (m == a) // error (good)
cout << "bad" << endl;
if (a == Mammal::deer) // error (good)
cout << "bad" << endl;
}
Conclusion:
enum class
es should be preferred because they cause fewer surprises that could potentially lead to bugs.
Enum in structure
Since C++11 you can use enum class
instead of enum
to solve this problem.
If you can't use C++11 for some reason you should prefix your values like this:
enum IN
{
IN_SYSTEMMONITOR,
IN_MODEMANAGEMENT
};
enum OUT
{
OUT_SLIDECONTROL,
OUT_MODEMANAGEMENT,
OUT_HMICONTROL,
OUT_MOTORCONTROL
};
or they can't be placed at the same structure, so you have to move the declarations to different namespaces. (EDIT: or different class / structure as it said below.)
Where should we put our enums?
The best descision depends on how the enumeration is used.
E.g.
- if the enumeration is only used in one class, you can make it an inner class to that class
- if the enumeration is used by one class (e.g.
A
) more than others (e.g. the others call methods onA
that have parameters of type of the enumeration; you might want to put it in the same package/namespace asA
is in.
In general, find the best package/namespace based on where its used most
Related Topics
How to Make a C++ Struct Value-Initialize All Pod Member Variables
Convert Integer to Binary and Store It in an Integer Array of Specified Size:C++
Unique_Ptr and Openssl's Stack_Of(X509)*
Using << Operator to Write to Both a File and Cout
Ifstream Not Reading Eof Character
Difference Between Regex_Match and Regex_Search
C++ Virtual Override Functions with Same Name
Multiple Sfinae Class Template Specialisations Using Void_T
Std::Async Won't Spawn a New Thread When Return Value Is Not Stored
C++11 Range Based Loop: How Does It Really Work
Array of Pointers as Function Parameter
Qt MACro Keywords Cause Name Collisions
Efficient Multiply/Divide of Two 128-Bit Integers on X86 (No 64-Bit)