Posts Tagged ‘scoped enums’

The namespace-enum trick

Enums in C++ can be a pain in the ass once a project starts to grow in size. Enums are typically defined globally or within a fairly wide scope such that there’s usually a pretty high probability that you’ll get name clashes between enums (remember that in C++ the enum block is not a scope, so enum members must be unique across multiple enum declarations) unless, like with the DirectX or Win32 APIs, you give your enum members names which are detailed, prefixed, and very ugly looking. For example here’s some of the enum members for Direct3D render states:

typedef enum _D3DRENDERSTATETYPE {
    D3DRS_ZENABLE = 7,
    D3DRS_FILLMODE = 8,
    D3DRS_SHADEMODE = 9,
    D3DRS_ZWRITEENABLE = 14,
    D3DRS_ALPHATESTENABLE = 15,
    ...

Truthfully, the DirectX enums aren’t that bad, and most programmers (including myself) have seen worse, but is there a better way?

Recently, I’ve discovered a cool trick that I’ve started using in most of my C++ code. Just wrap the enum declaration inside of a namespace. So, as an example, you might have something like:

namespace Color
{
    
enum Color
    {
        Red,
        Green,
        Blue,
        Orange,
        Purple
    }
}

… and, because of the namespace wrapper, it’s also perfectly valid to have the following within the same scope as the code above (note the Orange enum member in both declarations):

namespace Fruit
{
    
enum Fruit
    {
        Apple,
        Orange,
        Purple
    }
}

You access an enum member by simply resolving the namespace first:

Color::Red
Color::Orange
Fruit::Orange

Simple and elegant!

The only oddity is that to declare variables that are of the enum type, you have a declaration that looks like:

Fruit::Fruit

or

Color::Color

… but overall I think that’s a small price to pay.

I am very surprised that this little trick is not mentioned much and in the few places where I have seen it mentioned (such as here), it is glossed over and its significance is not really highlighted.

EDIT: Note that C++11 introduces scoped enums which renders this trick unnecessary, if you have a compliant compiler.