Scoped enums

Back to Deprecated techniques

This section was deprecated after Visual Studio 2013 implemented strongly typed enums; we have transitioned to use them. Below is the original text for historical reference.

In this section we present a technique for scoping enum values, i.e. simulating strongly typed enums. C++11 has this feature, but at the time of the last update of this section (June 2012), they aren’t yet implemented in Visual Studio 2010. While waiting for the support, we need something else. The following is what we have been using when working with C++03.

Problem

Consider the following code:

enum LoopType
{
    None,
    Forward,
    Backward,
    PingPong
};

enum Direction
{
    Forward,
    Backward,
    Left,
    Right
};

void setLoopType(LoopType loopType)
{
    // ...
}

void move(Direction direction)
{
    // ...
}

int main()   
{
    setLoopType(Forward);
    move(Backward);

    return 0;
}

This code won’t compile because the enum values collide in identifiers. This is because the enum values are not scoped inside LoopType and Direction. Instead, the enum values reserve identifiers from the surrounding namespace.

Solution

The solution is to wrap enums inside a class, in effect offering the enum values their own namespace:

class LoopType
{
public:
    enum Enum
    {
        None,
        Forward,
        Backward,
        PingPong
    };
};

class Direction
{
public:
    enum Enum
    {
        Forward,
        Backward,
        Left,
        Right
    };
};

void setLoopType(LoopType::Enum loopType)
{
    // ...
}

void move(Direction::Enum direction)
{
    // ...
}

int main()   
{
    setLoopType(LoopType::Forward);
    move(Direction::Backward);

    return 0;
}

The extra effort you need to do now is to rewrite the types of the enums as LoopType::Enum and Direction::Enum instead of just LoopType and Direction. Additionally, you always have to be explicit with the enum values, qualifying the enum of which you are referring to (e.g. LoopType::Forward). I find the the enum type name (e.g. LoopType::Enum) nice because it is in symmetry with the enum value names (e.g. LoopType::Forward) as if saying ‘replace Enum with your desired enum value’.