Wednesday, 28 December 2011

Namespaced enums

One of the problems with enums is that the enumerators aren't scoped to the enum, but rather are in the same scope as the enum itself. That is:

enum Direction
{
    Left,
    Right,
    Up,
    Down
};

// Direction, Left, Right, Up and Down all defined here

This legacy behaviour from C causes problems when other similarly-named enumerators occur in the same scope:

enum QuestionResult
{
    Wrong,
    Right // error - Right already defined
};

People often add prefixes to limit this kind of collision:

enum Direction
{
    Dir_Left,
    Dir_Right,
    Dir_Up,
    Dir_Down
};

enum QuestionResult
{
    QR_Wrong,
    QR_Right
};

But this is C++! We have a solution for this type of problem, and it doesn't involve adding warts to our identifiers. We have namespaces:

namespace Direction
{
    enum type
    {
        Left,
        Right,
        Up,
        Down
    };
}

namespace QuestionResult
{
    enum type
    {
        Wrong,
        Right
    };
}

That way, you can use them like any namespaced entity:

obj.SetDirection(Direction::Right);
question.SetResult(QuestionResult::Right);

I've called my enums 'type' to match similar C++ constructs, like metafunctions, but it only really matters to be consistent within a program.

And this won't be an issue when C++11's enum class feature becomes sufficiently supported. Assuming no more portability disasters like nullptr.

No comments:

Post a Comment