为什么作用域枚举允许使用| 使用先前分配的值进行初始化时的运算符?

Dia*_*ius 12 c++ enums bitwise-operators language-lawyer

我正在将无范围的枚举转换为范围枚举,并且遇到了一个难题。

斯特劳斯,C ++编程语言,第4版,第8.4.1节中,作用域枚举类不隐式转换为整数类型,并为运营商提供的代码文件|,并&为如何用一个例子static_cast来工作的解决这一问题。

使用|运算符对先前定义的enum值进行的以下初始化不合法吗?

enum class FileCopy {
    PreviousHDUs   = 1,
    CurrentHDU     = 2,
    FollowingHDUs  = 4,
    AllHDUs        = PreviousHDUs | CurrentHDU | FollowingHDUs,
    CurrentHeader  = 8
};

int main()
{
    std::cout << static_cast<int>( FileCopy::AllHDUs) << "\n";
}
Run Code Online (Sandbox Code Playgroud)

我已经在Wandbox上使用clang和gcc HEAD进行了测试--pedantic-errors,它会编译并返回预期的输出7。这并不是说合法,只是编译器似乎接受了它。

是否有明确记录的行为?我一直无法以描述此行为的方式来解析文档

Bri*_*ian 9

[dcl.enum] / 5:

...如果基础类型是固定的,则闭括号前的每个枚举器的类型为基础类型...

也就是说,每个枚举器都有类型,int直到遇到右括号为止。此后,枚举数具有类型FileCopy,您将无法再像这样按位或它们。

  • 而且这还允许您使用其他算术运算,例如`enum class {A,B = A + 2};` (2认同)

Vla*_*cow 5

根据C ++ 17标准(8.5.13按位或运算符)

1执行通常的算术转换(8.3);结果是其操作数的按位或运算。运算符仅适用于整数或无范围的枚举操作数。

和(10.2枚举声明)

  1. ... 对于作用域枚举类型,如果未明确指定基础类型,则基础类型为int。在这两种情况下,底层类型都被认为是固定的。在枚举说明符的右括号之后,每个枚举器都有其枚举的类型。如果基础类型是固定的,则在右括号之前的每个枚举器的类型都是基础类型,并且枚举器定义中的常量表达式应是基础类型的转换后的常量表达式

因此,这是明确记录的行为。