Enum Enum: Only A Muppet Would Use The Old Form

I always found the handling of enumerated types in the original C++ standard to be a weak point of the language. Generally, wherever braces are used a new level of scope is defined… except in the case of enums it would seem.

For example, it is not unreasonable to expect the following to compile without error (as the equivalent would do in C#, for example):

class Elevator
    enum DoorStatus { Open, Closed };
    enum MaintenanceIssueStatus { Open, Closed };

Unfortunately, reasonable is not going to cut it as this code gives us a ‘redefinition’ compiler error. Those naughty braces are not actually setting any scope at all here.

At least in the example above the enum is within a class (and possibly a namespace) so some level of control over scope is in place… an enum floating in the global namespace will cause as many issues as any other global.

As an aside, in some ways we can consider enums as not much more than another means of declaring integer variables, certainly in terms of scope anyway (at least enum does enforce casting to the type). Although by no means recommended, the above code could actually be achieved by the following (which would also suffer from the same compilation error of course):

class Elevator
    typedef int DoorStatus;
    typedef int MaintenanceIssueStatus;

    static const DoorStatus Open = 0;
    static const DoorStatus Closed = 1;
    static const MaintenanceIssueStatus Open = 0;
    static const MaintenanceIssueStatus Closed = 1;

Anyway, after a deep sigh, we usually have got around these sort of naming conflicts by the use of prefixes:

enum DoorStatus { ds_Open, ds_Closed };
enum MaintenanceIssueStatus { mis_Open, mis_Closed };

Thankfully all this nonsense came to an end with the C++11 standard. We now have enum class to work with. This neatly addresses the weaknesses of the standard enum:

enum class DoorStatus { Open, Closed };
enum class MaintenanceIssueStatus { Open, Closed };

Another benefit is this new style is strongly typed as, although the ‘old’ enum did require an explicit cast to convert from an integral type to an enum, conversion the other way was always implicit and so could lead to errors. So this type of issue can now be avoided:

class Elevator
    // Use of enum rather than enum class can easily hide
    // problems.
    enum DoorStatus { ds_Open, ds_Closed };
    enum IssueStatus { is_Open, is_Closed };

    void GotoFloor(int floorNum, bool leaveDoorsOpen = false);

// Oh no! Someone amended the Elevator class interface and
// now we are off to the 4th floor with the doors open...
Elevator e;
e.GotoFloor(4, DoorStatus::ds_Closed);

One comment

  1. This is aa great post

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: