根据标准设置的颜色是什么?
引用 C++11 和 C++14 标准的引用来回答:
[expr.static.cast]/10
整数或枚举类型的值可以显式转换为枚举类型。如果原始值在枚举值 (7.2) 的范围内,则该值不变。否则,结果值是未指定的(并且可能不在该范围内)。
让我们查看枚举值的范围:[dcl.enum]/7
对于基础类型固定的枚举,枚举的值是基础类型的值。
在 CWG 1766 (C++11, C++14) 之前
因此,对于data[0] == 100
,结果值被指定(*),并且不涉及未定义行为(UB) 。更一般地,当您从基础类型转换为枚举类型时,没有任何值data[0]
可以导致static_cast
.
在 CWG 1766 (C++17) 之后
请参阅CWG 缺陷 1766。[expr.static.cast]p10 段落已得到加强,因此如果将枚举的可表示范围之外的值强制转换为枚举类型,则现在可以调用 UB。这仍然不适用于问题中的场景,因为data[0]
它是枚举的基础类型(见上文)。
请注意,CWG 1766 被认为是标准中的一个缺陷,因此编译器实现者可以将其应用于其 C++11 和 C++14 编译模式。
(*)char
要求至少为 8 位宽,但不要求为unsigned
. 可存储的最大值至少要127
符合 C99 标准的附录 E。
与 [expr]/4 比较
如果在计算表达式期间,结果未在数学上定义或不在其类型的可表示值范围内,则行为未定义。
在 CWG 1766 之前,转换整数类型 -> 枚举类型可以产生未指定的值。问题是:未指定的值是否可以超出其类型的可表示值?我相信答案是否定的——如果答案是肯定的,那么“此操作产生未指定的值”和“此操作具有未定义的行为”之间的有符号类型操作的保证不会有任何区别。
因此,在 CWG 1766 之前,甚至不会static_cast<Color>(10000)
调用UB;但在 CWG 1766 之后,它确实调用了 UB。
现在,switch
声明:
[stmt.switch]/2
条件应为整数类型、枚举类型或类类型。[...]进行整体促销。
[conv.prom]/4
其基础类型固定 (7.2)的无作用域枚举类型的纯右值可以转换为其基础类型的纯右值。此外,如果可以将整数提升应用于其基础类型,则其基础类型固定的无范围枚举类型的纯右值也可以转换为提升的基础类型的纯右值。
注意:没有enum-base的作用域枚举的基础类型是int
. 对于无范围枚举,底层类型是实现定义的,但不应大于int
如果int
可以包含所有枚举数的值。
对于无范围的枚举,这导致我们 /1
如果可以表示源类型的所有值,则可以将除bool
, char16_t
,之外的整数类型的纯右值char32_t
,或者wchar_t
其整数转换等级(4.13)小于等级的int
纯右值转换为类型的纯右值;否则,源纯右值可以转换为类型的纯右值。int
int
unsigned int
在无范围枚举的情况下,我们将在此处处理int
s。对于范围枚举 (enum class
和enum struct
),不适用整体提升。无论如何,整体提升也不会导致 UB,因为存储的值在基础类型的范围内,并且在int
.
[stmt.switch]/5
执行语句时switch
,会评估其条件并与每个 case 常量进行比较。如果 case 常量之一等于条件的值,则将控制传递给匹配case
标签后面的语句。如果没有case
常量与条件匹配,并且如果有default
标签,则控制传递到由default
标签标记的语句。
default
标签应该被击中。
注意:可以再看一下比较运算符,但它没有在所提到的“比较”中明确使用。事实上,在我们的例子中,没有任何迹象表明它会为作用域或非作用域枚举引入 UB。
作为奖励,标准是否对此做出任何保证,但使用普通枚举?
是否enum
是作用域在这里没有任何区别。但是,底层类型是否固定确实会有所不同。完整的 [decl.enum]/7 是:
对于基础类型固定的枚举,枚举的值是基础类型的值。否则,对于其中e min是最小枚举数并且e max是最大枚举数的枚举,枚举的值是b min到b max范围内的值,定义如下: 让K
be1
对于二进制补码表示和0
对于 a一个的补码或符号幅度表示。b max是大于或等于max(|e min | − K
, |e max |)且等于2的最小值M − 1,其中M
是一个非负整数。如果e min为非负数,则b min为零,否则为-(b max + )。K
让我们看一下下面的枚举:
enum ColorUnfixed /* no fixed underlying type */
{
red = 0x1,
yellow = 0x2
}
请注意,我们不能将其定义为范围枚举,因为所有范围枚举都有固定的基础类型。
幸运的是,ColorUnfixed
的最小枚举数是red = 0x1
,所以max(|e min | − K
, |e max |)等于|e max | 无论如何,这是yellow = 0x2
. 大于或等于 的最小值,对于正整数2
等于2 M - 1M
是3
( 2 2 - 1 )。(我认为目的是允许范围以 1 位为单位扩展。)因此b max is3
和bmin is 0
。
因此,100
将超出 的范围ColorUnfixed
,并且static_cast
在 CWG 1766 之前会产生未指定的值,在 CWG 1766 之后会产生未定义的行为。