如果一个枚举无法适合一个无符号整型,会发生什么?
按照Bathsheba的要求,并作为“如果枚举不能整合到一个types中会发生什么?”的后续问题。 :
假设一个枚举定义如下:
enum foo : unsigned int { bar = UINT_MAX, oops };
oops
的价值是定义的还是不是?
MSVS2015编译:
warning C4340: 'oops': value wrapped from positive to negative value warning C4309: 'initializing': truncation of constant value warning C4369: 'oops': enumerator value '4294967296' cannot be represented as 'unsigned int', value is '0'
MSVS2015输出:
bar = 4294967295 oops= 0
gcc 4.9.2编译:
9 : note: in expansion of macro 'UINT_MAX' bar = UINT_MAX, ^ 10 : error: enumerator value 4294967296l is outside the range of underlying type 'unsigned int' oops ^ Compilation failed
gcc 4.9.2输出
//compilation failed
这是一个非常有趣的问题。 简单的答案是,这是从字面上来说是不确定的:标准没有对这种情况说什么。
为了有一个更好的例子,考虑这个enum
:
enum foo : bool { True=true, undefined };
按照标准:
[ dcl.enum ] / 2 :[…]没有初始化器的枚举器定义给枚举器通过将前一个枚举器的值加1而获得的值。
因此,在我们的例子中foo::undefined
的值是2
( true+1
)。 这不能被表示为一个bool
。
它是不合格的吗?
不 ,根据标准,这是完全有效的,只有没有固定的基础types有一个限制,不能够代表所有的枚举值:
[ dcl.enum ] / 7 :对于其基础types不固定的枚举,[…]如果没有整型可以表示所有的枚举值,则枚举是不合格的。
它没有提到一个固定的底层types ,它不能代表所有的枚举值。
什么是原始问题的oops
的价值和undefined
?
这是不明确的 :标准没有对这种情况说任何东西。
foo::undefined
可能值:
- 最高可能值(
true
):undefined
,oops
应该是基础types的最大值。 - 可能的最低值(
false
): 底层types的最小值。 注意:在有符号整数中,它不会与整数溢出(未定义行为)的当前行为相匹配。 - 随机值(?):编译器会select一个值。
所有这些值的问题是,它可能会导致两个字段具有相同的值(例如foo::True == foo::undefined
)。
初始值 (例如undefined=2
)和“隐式”初始值(例如True=true, undefined
)
按照标准:
[ dcl.enum ] / 5 :如果基础types是固定的,则在大括号之前的每个枚举器的types是底层types , 枚举器定义中的常量expression式应该是基础types的转换常量expression式。
换一种说法:
enum bar : bool { undefined=2 };
相当于
enum bar : bool { undefined=static_cast<bool>(2) };
然后bar::undefined
将true
。 在“隐式”初始化器中,情况并非如此:这个标准段落只是说明了初始化器 ,而不是“隐式”初始化器。
概要
- 通过这种方式, 固定基础types的
enum
可能具有不可表示的值。 - 他们的价值是不确定的标准。
根据问题和意见,这在GCC和叮当中是无效的,但对MSVS-2015有效(有警告)。