Enums vs enum class in C++


Welcome to the next pikoTutorial!

When dealing with enumerations in C++, developers have two primary options: traditional enum and enum class.

Traditional enums vs enum classes

At the first glance, the only difference appears to be in the class keyword:

enum TraditionalEnumError
{
    kServiceNotAvailable,
    kInvalidArguments,
};

enum class EnumClassError
{
    kServiceNotAvailable,
    kInvalidArguments,
};

The real difference is however in how both of them behave.

Usage

The first real difference appears when you want to use the enum. While traditional enum value can be used either with full name or only the field name, enum class must be used with the full name:

TraditionalEnumError value_from_full_name = TraditionalEnumError::kServiceNotAvailable;
TraditionalEnumError only_value = kServiceNotAvailable;
EnumClassError value_from_full_name = EnumClassError::kServiceNotAvailable;
EnumClassError only_value = kServiceNotAvailable; // compilation error

Implicit conversion

While traditional enums allow for implicit conversions, enum classes forbid this to prevent unintended conversion. This makes enum class a strong type which can’t be mixed together with other types.

int traditional_enum_value = TraditionalEnumError::kServiceNotAvailable;
int enum_class_value = EnumClassError::kServiceNotAvailable; // compilation error

If you really need to convert enum class to the underlying integer value, you must do an explicit cast:

int enum_class_value = static_cast<int>(EnumClassError::kServiceNotAvailable);

Scoped names

The names in enum class object are scoped within the given enum class what prevents name clashes and scope polluting. This solves the problem related to the fact that if you try to define 2 different traditional enums, but any of their fields repeats, you’ll get a compilation error informing about the name clash.

enum class EnumClass1 { kValue };
enum class EnumClass2 { kValue }; // this kValue repetition is ok thanks to enum class scoping
enum TraditionalEnum1 { kValue };
enum TraditionalEnum2 { kValue }; // compilation error - duplicated kValue from TraditionalEnum1