根据标准颜色设置为多少?
引用 C++11 和 C++14 标准来回答:
[expr.static.cast]/10
整型或枚举类型的值可以显式转换为枚举类型。如果原始值在枚举值(7.2)的范围内,则该值不变。否则,结果值是未指定的(并且可能不在该范围内)。
我们来查一下枚举值的范围: [dcl.enum]/7
对于基础类型固定的枚举,枚举的值是基础类型的值。
CWG 1766 之前(C++11、C++14)因此,对于data[0] == 100
,结果值被指定(*),并且没有未定义行为 (UB) https://stackoverflow.com/q/2766731/420683参与。更一般地,当您从基础类型转换为枚举类型时,没有值data[0]
可以导致 UBstatic_cast
.
CWG 1766 (C++17) 之后
See CWG 缺陷 1766 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1766。
[expr.static.cast]p10 段落已经得到加强,所以你现在can如果将枚举可表示范围之外的值转换为枚举类型,则调用 UB。这仍然不适用于问题中的场景,因为data[0]
是枚举的基础类型(见上文)。
请注意,CWG 1766 被认为是标准中的缺陷,因此编译器实现者接受将其应用于其 C++11 和 C++14 编译模式。
(*) char
is required to be at least 8 bit wide, but isn't required to be unsigned
. The maximum value storable is required to be at least 127
per Annex E of the C99 Standard.
与 [expr]/4 比较
如果在计算表达式期间,结果未在数学上定义或不在其类型的可表示值范围内,则行为未定义。
在 CWG 1766 之前,转换整型 -> 枚举类型可以产生一个未指定值。问题是:未指定的值是否可以超出其类型的可表示值?我相信答案是no——如果答案是yes,在“此操作产生未指定的值”和“此操作具有未定义的行为”之间,对有符号类型的操作获得的保证不会有任何差异。
因此,在 CWG 1766 之前,即使static_cast<Color>(10000)
would not调用 UB;但在 CWG 1766 之后,does调用 UB。
现在switch
陈述:
[stmt.开关]/2
条件必须是整型、枚举类型或类类型。 [...]进行积分促销。
[会议舞会]/4
的纯右值unscoped基础类型固定的枚举类型 (7.2) 可以转换为其基础类型的纯右值。此外,如果整数提升可以应用于其基础类型,则基础类型固定的无作用域枚举类型的纯右值也可以转换为提升的基础类型的纯右值。
Note: The underlying type of a scoped enum w/o enum-base is int
. For unscoped enums the underlying type is implementation-defined, but shall not be larger than int
if int
can contain the values of all enumerators.
For an 无作用域枚举,这导致我们 /1
除以下整数类型的纯右值bool
, char16_t
, char32_t
, or wchar_t
其整数转换等级 (4.13) 小于int
可以转换为类型的纯右值int
if int
可以表示源类型的所有值;否则,源纯右值可以转换为类型的纯右值unsigned int
.
如果是unscoped枚举,我们将处理int
在这里。为了scoped枚举(enum class
and enum struct
),不适用积分促销。无论如何,积分提升也不会导致 UB,因为存储的值在基础类型的范围内并且在int
.
[stmt.开关]/5
当。。。的时候switch
执行语句时,会评估其条件并与每个 case 常量进行比较。如果其中一个 case 常量等于条件的值,则控制权将传递给匹配的后面的语句case
标签。如果不case
常量匹配条件,如果有default
标签,控制传递到由标签标记的语句default
label.
The default
应该打标签。
Note: One could take another look at the comparison operator, but it is not explicitly used in the referred "comparison". In fact, there's no hint it would introduce UB for scoped or unscoped enums in our case.
作为奖励,该标准是否对此做出任何保证,但使用普通枚举?
无论是否enum
范围在这里没有任何区别。但是,基础类型是否固定确实会产生影响。完整的 [decl.enum]/7 是:
For an enumeration whose underlying type is fixed, the values of the enumeration are the values of the underlying type. Otherwise, for an enumeration where emin is the smallest enumerator and emax is the largest, the values of the enumeration are the values in the range bmin to bmax, defined as follows: Let K
be 1
for a two's complement representation and 0
for a one's complement or sign-magnitude representation. bmax is the smallest value greater than or equal to max(|emin| − K
, |emax|) and equal to 2M − 1, where M
is a non-negative integer. bmin is zero if emin is non-negative and −(bmax + K
) otherwise.
我们来看看下面的枚举:
enum ColorUnfixed /* no fixed underlying type */
{
red = 0x1,
yellow = 0x2
}
请注意,我们不能将其定义为作用域枚举,因为所有作用域枚举都有固定的基础类型。
Fortunately, ColorUnfixed
's smallest enumerator is red = 0x1
, so max(|emin| − K
, |emax|) is equal to |emax| in any case, which is yellow = 0x2
. The smallest value greater or equal to 2
, which is equal to 2M - 1 for a positive integer M
is 3
(22 - 1). (I think the intent is to allow the range to extent in 1-bit-steps.) It follows that bmax is 3
and bmin