Skip to content

Wiki

enum class

About 8 min read

1.What problem does this section solve?

C language's enum There are several issues:

  1. Name pollution:Enumeration values leak into the scope in which they are defined; for example, after writing enum Color { red, green }; ,red becomes a global name and cannot be used for another enumeration.
  2. Implicit conversion to integer:Enumeration values silently become integers when participating in operations (red + 1 is legal but usually meaningless).
  3. Underlying type is unspecified:The compiler decides on its own how much space to use to store enumeration values.

enum class All the above problems have been solved.

2.What is this feature?

enum class(Strongly typed enums / scoped enums) are an improved version of enums introduced in C++11:

  • Enumeration values havescope qualificationand need to be accessed usingColor::red.
  • will notbe implicitly converted to integers.
  • canspecify the underlying type(such asenum class Color : uint8_t).

3.C++ Standard Edition

C++11

4.Required header files

No additional header files are required.enum class It is a language keyword. To use fixed-width integers such as uint8_t as the underlying type, #include <cstdint> is required.

5.Basic syntax

enum class 枚举名 : 底层类型
{
    值1,
    值2,
    值3
};

// 访问
枚举名 变量 = 枚举名::值1;

6.Common Usage

Usage Description
enum class E { A, B, C }; Basic enumeration class
enum class E : uint8_t { A, B, C }; Specify the underlying type
E::A Access enumeration value (scoped)
static_cast<int>(E::A) Explicit conversion (no implicit conversion)
switch (val) { case E::A: ... } switch matching

7.Example code

7.1.Example 1: Old enum vs enum class

#include <iostream>

// 旧式 enum(不推荐)
enum OldColor { red, green, blue };

// enum class(推荐)
enum class Color { red, green, blue };

int main()
{
    // 旧式 enum:名字污染,red 直接可见
    OldColor oc = red;  // 直接写 red
    int n = red;         // 隐式转为 0

    // enum class:需要带作用域
    Color c = Color::red;

    // int m = Color::red;  // ❌ 编译错误!不会隐式转换为 int
    int m = static_cast<int>(Color::red);  // ✅ 显式转换

    std::cout << "OldColor red = " << n << "\n";
    std::cout << "Color::red = " << m << "\n";

    return 0;
}

Running result:

OldColor red = 0
Color::red = 0

7.2.Example 2: Based on Example 1, specify the underlying type and custom values

#include <cstdint>
#include <iostream>

// 指定底层类型为 uint8_t(只占一个字节)
enum class Status : uint8_t
{
    Idle = 0,
    Running = 10,
    Paused = 20,
    Stopped = 30
};

void print_status(Status s)
{
    switch (s)
    {
        case Status::Idle:
            std::cout << "Idle\n";
            break;
        case Status::Running:
            std::cout << "Running\n";
            break;
        case Status::Paused:
            std::cout << "Paused\n";
            break;
        case Status::Stopped:
            std::cout << "Stopped\n";
            break;
    }
}

int main()
{
    Status s1 = Status::Running;
    print_status(s1);
    print_status(Status::Stopped);

    // 查看底层整数值
    std::cout << "sizeof(Status) = " << sizeof(Status) << " byte(s)\n";
    std::cout << "Running = " << static_cast<int>(Status::Running) << "\n";

    return 0;
}

Running result:

Running
Stopped
sizeof(Status) = 1 byte(s)
Running = 10

7.3.Example 3: Building on Example 2, application of enum class in a struct

#include <iostream>
#include <string>

enum class Grade
{
    A = 90,
    B = 80,
    C = 70,
    D = 60,
    F = 0
};

struct Student
{
    std::string name;
    Grade grade;
};

std::string grade_to_string(Grade g)
{
    switch (g)
    {
        case Grade::A: return "A (优秀)";
        case Grade::B: return "B (良好)";
        case Grade::C: return "C (中等)";
        case Grade::D: return "D (及格)";
        case Grade::F: return "F (不及格)";
        default:       return "未知";
    }
}

int main()
{
    Student s1{"Alice", Grade::A};
    Student s2{"Bob", Grade::C};

    std::cout << s1.name << " grade: " << grade_to_string(s1.grade) << "\n";
    std::cout << s2.name << " grade: " << grade_to_string(s2.grade) << "\n";

    // 比较(enum class 支持 ==, <, > 等)
    if (s1.grade > s2.grade)
    {
        std::cout << s1.name << " has higher grade\n";
    }

    return 0;
}

Running result:

Alice grade: A (优秀)
Bob grade: C (中等)
Alice has higher grade

8.Operation result

See the "run results" for each example above.

9.Key syntax explanation in the example

Example What was discussed Newly introduced syntax Why it is written this way Notes
Example 1 Old enum problem vs enum class enum class、static_cast<int>() Old enum name pollution, implicit conversion to int; enum class solves this Must explicitly convert when an integer value is needed
Example 2 Specifying the underlying type and switch usage enum class : uint8_t、switch + enum class Specifying the underlying type can save memory (e.g., embedded scenarios) sizeof(enum class) is not equal to the number of members
Example 3 Using enum class in a struct enum class as a struct member, comparison operations Represents finite value sets such as states and levels enum class supports ==, <, > and other comparisons

10.enum class is suitable for representing states and options

enum class It is most suitable for representing "a finite number of discrete values," such as robot states, task phases, communication protocol commands, and UI modes.

10.1.Example 4: Representing robot states with enum class

#include <iostream>

enum class RobotState
{
    Idle,
    Running,
    Error
};

void handle_state(RobotState state)
{
    switch (state)
    {
        case RobotState::Idle:
            std::cout << "wait for command\n";
            break;
        case RobotState::Running:
            std::cout << "execute task\n";
            break;
        case RobotState::Error:
            std::cout << "stop and report error\n";
            break;
    }
}

int main()
{
    // 程序从 main 函数开始执行,下面的语句会按顺序运行。
    RobotState state = RobotState::Running;
    handle_state(state);

    // 返回 0 表示程序正常结束。
    return 0;
}

Running result:

execute task

If you use int state = 1 a reader of the code will not know what 1 is; if you use enum class RobotState::Running the semantics are written directly in the type, and it will not be confused with the Running of other enums.

11.Common Errors

Error 1: Directly using an enum class value as an array index

enum class Color { red, green, blue };
int counts[3];
counts[Color::red];  // ❌ 编译错误!不会隐式转换

Correct approach:counts[static_cast<int>(Color::red)] or consider using map in this scenario.

Error 2: Forgetting to write the scope prefix

enum class Status { Running, Stopped };
Status s = Running;  // ❌ 编译错误!缺少 Status::

Correct approach:Status s = Status::Running;

Error 3: Mixing values from different enum classes in a switch

switch (status)
{
    case Status::Running:  // ✅ 正确
    case Machine::Running: // ❌ 编译错误!不同枚举类型
        break;
}

Correct practice: the case in a switch must be of the same enum type as the switch expression.

12.Usage Recommendations

  1. Always use enum class instead of the old enum: type-safe, clear scoping.
  2. You can specify the underlying type:Use enum class : uint8_t in embedded scenarios to save space.
  3. When an integer value is needed, explicitly use static_cast: do not rely on implicit conversion.
  4. enum class is still an integer, can switch:with the default branch to handle unknown values.

13.Summary

  • enum class To avoid name pollution, enumeration values are accessed through 枚举名::值.
  • It is not implicitly converted to an integer; static_cast is required for explicit conversion.
  • An underlying type can be specified (enum class E : uint8_t).
  • It is suitable for representing finite sets of discrete values such as states, levels, and options.