PAYATHON 2026

scoped enum class 能否引用前序枚举值?

数据小许

结论

在 C++14 中,可以在同一个 enum class 定义里引用前面声明的枚举值。不过,下面这种直接相加的写法不合法:

enum class MyEnum_S : int {
    foo = 2,
    bar = 5,
    baz = foo + bar + 2
};

这是编译期的 ill-formed 错误,不是未定义行为。先用 static_cast<int> 将枚举值显式转换为整数,再进行算术运算,写法就有效;前提是计算结果能由底层类型 int 表示。

为什么直接相加不合法

enum class 是 scoped enum。它的枚举值类型为 MyEnum_S,不会像普通无作用域 enum 的枚举值那样隐式转换为整数。因此,表达式 foo + bar 没有适用的内置加法运算符。

在同一个枚举定义中,枚举值声明后就能用于后续的初始化表达式。问题出在算术类型上,而不是不能引用前面声明的名字。

可用写法

显式转换为底层整数类型后,就可以在枚举定义中计算后续值:

enum class MyEnum_S : int {
    foo = 2,
    bar = 5,
    baz = static_cast<int>(foo) + static_cast<int>(bar) + 2
};

也可以使用限定名:

enum class MyEnum_S : int {
    foo = 2,
    bar = 5,
    baz = static_cast<int>(MyEnum_S::foo)
       + static_cast<int>(MyEnum_S::bar)
       + 2
};

这两种写法都会先把枚举值转换为 int,再计算整数常量表达式。MyEnum_S 的底层类型明确指定为 int,因此初始化值必须能由 int 表示。示例的结果是 9,符合这个要求。

对照:无作用域 enum

普通无作用域 enum 的枚举值可以参与整数提升,因此类似写法是合法的:

enum MyEnum_U {
    u_foo = 2,
    u_bar = 5,
    u_baz = u_foo + u_bar + 2
};

差别在于无作用域 enum 和 scoped enum 的类型转换规则,而不是编译器能否引用前面声明的枚举值。

实际建议

如果后续枚举值需要根据前面的值计算,应在 enum class 初始化表达式中显式转换为底层整数类型。直接写 foo + bar 无法通过标准 C++ 编译;即使编译器接受,也不能据此认定代码符合标准。

备注:内容仅供参考。