如果你static_cast无效的值枚举类会发生什么?

考虑一下这个C ++ 11代码:

enum class Color : char { red = 0x1, yellow = 0x2 } // ... char *data = ReadFile(); Color color = static_cast<Color>(data[0]); 

假设数据[0]实际上是100.什么是根据标准设置的颜色? 特别是,如果我稍后做

 switch (color) { // ... red and yellow cases omitted default: // handle error break; } 

标准保证默认会被打中吗? 如果没有,那么在这里检查错误的适当,最有效,最优雅的方法是什么?

编辑:

作为一个奖励,标准是否作出这方面的保证,但明确枚举?

根据标准设定的颜色是什么?

回答标准报价:

[expr.static.cast] / 10

整数或枚举types的值可以显式转换为枚举types。 如果原始值在枚举值(7.2)的范围内,则该值不变。 否则,结果值是未指定的(可能不在该范围内)。

我们来查看枚举值范围 :[dcl.enum] / 7

对于基础types固定的枚举,枚举的值是基础types的值。

在CWG 1766之前因此,对于data[0] == 100 ,指定结果值(*),并且不包含未定义行为(UB) 。 更一般地说,当你从底层types转换为枚举types时, data[0]任何值都不会导致static_cast UB。

CWG 1766之后请参阅CWG缺陷1766 。 [expr.static.cast] p10的段落已经被加强了,所以现在你可以调用UB,如果你把一个枚举types的enum的可表示范围以外的值。

(*) char必须至less为8位宽,但不要求unsigned C99标准的附录E要求最大可存储值至less为127


比较[expr] / 4

如果在expression式评估过程中,结果不是math定义的,或者不在其types的可表示值范围内,则行为是未定义的。

所以如果值足够大的话,这很容易导致UB,例如static_cast<Color>(10000);


现在, switch语句:

[stmt.switch] / 2

条件应是整型,枚举型或types。 […] 积分促销活动。

[conv.prom / 4

基础types固定(7.2)的非型枚举types的前值可以转换为其基础types的前值。 而且,如果可以对其基础types应用整体提升,则基础types固定的非范型枚举types的前值也可以被转换为提升的基础types的前值。

注意:范围枚举w / o enum-base的基础types是int 对于unscoped枚举,底层types是实现定义的,但不能大于int如果int可以包含所有枚举值的值。

对于一个无法枚举的枚举 ,这导致我们到/ 1

除了boolchar16_tchar32_twchar_t其整数转换等级(4.13)小于int的等级)的inttypes的前值可以被转换为inttypes的prvalue,如果int可以表示源types的所有值; 否则,可以将源prvalue转换为unsigned inttypes的prvalue。

在枚举枚举的情况下,我们将在这里处理int 。 对于范围枚举( enum classenum struct ),不适用整体升级。 不pipe怎样,积分提升也不会导致UB,因为存储值在基础types的范围内,并且在int的范围内。

[stmt.switch] / 5

执行switch语句时,会评估其条件并与每个case常量进行比较。 如果其中一个case常量等于条件的值,则控制权将传递给匹配的case标签之后的语句。 如果没有case匹配的条件,并且如果有一个default标签,控制权传递给default标签标记的语句。

default标签应该被打。

注意:可以再看看比较运算符,但是在引用的“比较”中没有明确地使用它。 事实上,在我们的例子中没有提到将UB引入范围或无限范围的枚举。


作为一个奖励,标准是否作出这方面的保证,但明确枚举?

enum的范围是否在这里没有任何区别。 但是,底层types是否是固定的,是有区别的。 完整的[decl.enum] / 7是:

对于基础types固定的枚举,枚举的值是基础types的值。 否则,对于其中emin是最小枚举数并且e max是最大枚举的枚举,枚举的值是在范围b minb max中的值 ,定义如下:对于二的补码表示设K10表示补码或符号幅度表示。 b max是大于或等于max(| e min | – K ,| e max |)且等于2 M – 1的 最小值 ,其中M是非负整数。 如果e min是非负的,那么b min是零,否则是(b max + K

幸运的是,你枚举的最小枚举符是red = 0x1 ,所以max(| e min | – K ,| e max |)等于| e max | 在任何情况下,这是yellow = 0x2 。 对于正整数M ,大于或等于2的最小值等于2 M -1 ,为32 2 -1 )。 (我认为目的是允许范围以1位的步长扩展 )。因此, b max3bmin0

因此, 100会超出枚举的范围, static_cast会产生一个未指定的值,这可能导致UB按照[expr] / 4。