namespaces for enum types - best practices
Often, one needs several enumerated types together. Sometimes, one has a name clash. Two solutions to this come to mind: use a namespace, or use 'larger' enum element names. Still, the namespace solution has two possible implementations: a dummy class with nested enum, or a full blown namespace.
I'm looking for pros and cons of all three approaches.
Example:
// oft seen hand-crafted name clash solution
enum eColors { cRed, cColorBlue, cGreen, cYellow, cColorsEnd };
enum eFeelings { cAngry, cFeelingBlue, cHappy, cFeelingsEnd };
void setPenColor( const eColors c ) {
switch (c) {
default: assert(false);
break; case cRed: //...
break; case cColorBlue: //...
//...
}
}
// (ab)using a class as a namespace
class Colors { enum e { cRed, cBlue, cGreen, cYellow, cEnd }; };
class Feelings { enum e { cAngry, cBlue, cHappy, cEnd }; };
void setPenColor( const Colors::e c ) {
switch (c) {
default: assert(false);
break; case Colors::cRed: //...
break; case Colors::cBlue: //...
//...
}
}
// a real namespace?
namespace Colors { enum e { cRed, cBlue, cGreen, cYellow, cEnd }; };
namespace Feelings { enum e { cAngry, cBlue, cHappy, cEnd }; };
void setPenColor( const Colors::e c ) {
switch (c) {
default: assert(false);
break; case Colors::cRed: //...
break; case Colors::cBlue: //...
//...
}
}
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.
FYI In C++0x there is a new syntax for cases like what you mentioned (see C++0x wiki page)
enum class eColors { ... };
enum class eFeelings { ... };
I've hybridized the preceding answers to something like this: (EDIT: This is only useful for pre- C++11. If you are using C++11, use enum class
)
I've got one big header file that contains all my project enums, because these enums are shared between worker classes and it doesn't make sense to put the enums in the worker classes themselves.
The struct
avoids the public: syntactic sugar, and the typedef
lets you actually declare variables of these enums within other worker classes.
I don't think using a namespace helps at all. Maybe this is because I'm a C# programmer, and there you have to use the enum type name when referring the values, so I'm used to it.
struct KeySource {
typedef enum {
None,
Efuse,
Bbram
} Type;
};
struct Checksum {
typedef enum {
None =0,
MD5 = 1,
SHA1 = 2,
SHA2 = 3
} Type;
};
struct Encryption {
typedef enum {
Undetermined,
None,
AES
} Type;
};
struct File {
typedef enum {
Unknown = 0,
MCS,
MEM,
BIN,
HEX
} Type;
};
...
class Worker {
File::Type fileType;
void DoIt() {
switch(fileType) {
case File::MCS: ... ;
case File::MEM: ... ;
case File::HEX: ... ;
}
}