CppEnumerations

Enumerations

An enumeration (enum) lets you define a type whose values are restricted to a named set of options, which makes code far more readable than using raw integers to represent a fixed set of choices.
Plain enum (C-Style, Unscoped)

CPP
enum Color { RED, GREEN, BLUE };

int main() {
    Color favorite = GREEN;

    if (favorite == GREEN) {
        // ...
    }

    int rawValue = favorite; // implicit conversion to int is allowed: 1
    return 0;
}
Unscoped enum pitfalls
A plain enum's values (RED, GREEN, BLUE) leak into the surrounding scope, so they can collide with other names — you cannot have another enum or constant named RED in the same scope. Plain enums also convert implicitly to int, which means the compiler will not stop you from comparing or mixing unrelated enums, or assigning an out-of-range integer.
enum class (Scoped, C++11+)
enum class (also called a scoped enumeration) fixes both problems: its values live inside the enum's own namespace, and it does not implicitly convert to int.

CPP
enum class Color { Red, Green, Blue };
enum class TrafficLight { Red, Yellow, Green }; // no collision with Color::Red

int main() {
    Color favorite = Color::Green;   // must qualify with the enum name

    if (favorite == Color::Green) {
        // ...
    }

    // int rawValue = favorite;       // ERROR: no implicit conversion to int
    int rawValue = static_cast<int>(favorite); // must cast explicitly

    return 0;
}
enum vs enum class

Aspect

enum (unscoped)

enum class (scoped)

Introduced

C (pre-C++)

C++11

Namespace pollution

Yes — values leak into enclosing scope

No — values require EnumName::Value

Implicit conversion to int

Yes

No — requires static_cast

Comparing across different enums

Allowed (dangerous)

Not allowed — compile error

Recommended for new code

No

Yes

Specifying the Underlying Type

By default the compiler picks an underlying integer type large enough to hold all the enumerators. You can specify it explicitly — useful when the enum is serialized, stored compactly, or needs a predictable size.

CPP
#include <cstdint>

enum class Color : uint8_t { Red, Green, Blue }; // guaranteed 1 byte

int main() {
    Color c = Color::Blue;
    return 0;
}
Note
Specifying an underlying type also lets you **forward-declare** an enum (enum class Color : uint8_t;) without listing its enumerators, which can reduce header dependencies in large projects.
Using Enums in a switch Statement
Enums pair naturally with switch statements, which we cover in depth on its own page. Here is a quick preview:

CPP
#include <iostream>

enum class Color { Red, Green, Blue };

std::string colorName(Color c) {
    switch (c) {
        case Color::Red:   return "Red";
        case Color::Green: return "Green";
        case Color::Blue:  return "Blue";
    }
    return "Unknown";
}

int main() {
    std::cout << colorName(Color::Green) << std::endl;
    return 0;
}
  • Prefer enum class for all new code — it is safer with no meaningful downside

  • Use a plain enum only when interoperating with older C-style APIs that expect implicit int conversion

  • A switch over an enum class still requires qualifying each case with EnumName::Value