36

首先,我想说,根据 cppreference.com,对枚举进行值初始化有点不可能。

根据http://en.cppreference.com/w/cpp/language/value_initialization,值初始化枚举实际上执行零初始化。然后,根据http://en.cppreference.com/w/cpp/language/zero_initialization,对枚举进行零初始化的效果是:

如果T是标量类型,则对象的初始值是整数常量零隐式转换为T

但是,整数常量 0 不能隐式转换为枚举。最终,枚举不能进行值初始化。这听起来很奇怪,并且值初始化枚举确实适用于 VC、GCC 和 clang。那么,标准对此有何评论?

其次,根据http://en.cppreference.com/w/cpp/language/static_cast

整数、浮点或枚举类型可以转换为任何完整的枚举类型(结果未指定(C++17 前)未定义行为(C++17 起)如果表达式的值,转换为枚举的基础类型, 不是目标枚举值之一)

0那么,这是否意味着如果目标枚举没有一个等于

4

2 回答 2

4

评论中给出了这个问题的答案。下面给出了我试图解释其背后的整个标准的尝试。

对类型的对象或引用进行零初始化T意味着:

  • 如果T是标量类型(3.9),则将对象初始化为通过将整型文字0(零)转换为 获得的值T

(枚举是标量类型;第 3.9/9 节)因此,由于转换不是隐式的,所以我们不是在第 4 节,而是在第 5.2.9 节;

表达式static_cast<T>(v)的结果是将表达式转换v为 type的结果T

§5.2.9/10 然后定义如何将整数值转换为枚举类型。

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

必须表明,零在所有枚举的枚举值范围内。
接下来的五个引用取自第 7.2/8 节:

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

由于所有允许的基础类型在其值范围内都包含零*,因此这会自动给出所需的结果。现在,对于没有固定基础类型的枚举,

否则,对于其中e min是最小枚举数并且e max是最大枚举数的枚举,枚举的值是b minb max范围内的值,定义如下:

即我们必须证明b min总是小于或等于0,并且b max总是大于或等于0。

K为 1 表示二进制补码,0 表示一个补码或符号幅度表示。
b max是大于或等于max(|e min | − K, |e max |)并等于2M − 1的最小值,其中 M是非负整数。

|最大| 是非负数,并且两个数的最大值至少与两个数一样大。因此max(|e min | − K, |e max |)也是非负数,并且b max必须大于或等于该数字 - 所以我们的第一个要求得到满足。

如果e min为非负数,则b min为零,否则为-(b max + K)

b min显然为零或负数:b max如上所示为非负数,K为非负数(0 或 1),因此它们和的加法逆是非正数。我们的第二个要求得到满足。最后,

如果enumerator-list为空,则枚举的值就好像该枚举具有一个带有 value 的枚举数0

这通过设置e min = e max = 0导致上述结果。


  • 这简化为“所有整数类型在其值范围内都为零”的说法,这留给读者来证明。
于 2015-05-10T16:30:51.553 回答
3

1:这可能无法理解:

enum class SomeEnum : int { V1 = 0, V2 = 1, V3 = 2 }; 
SomeEnum a = 0; // compile error
SomeEnum b = SomeEnum.V1; // OK

这是对未定义行为的基本保护!

2:是的,是的:)

SomeEnum c = static_cast<SomeEnum>(1); // = SomeEnum.V2
SomeEnum d = static_cast<SomeEnum>(5); // undefined behavior

static_cast 根据定义是危险的,它应该只用于支持序列化或旧的 c 接口!

于 2015-03-05T15:11:25.817 回答