所有 C++ 枚举都至少有两个合法值吗?

Spe*_*cer 12 c++ enums language-lawyer

在使用一些自定义比较器时,我遇到了对仅具有单个可能值的类型的需求。存在类似std::nullptr_t和 空结构这样的类型。

然后我考虑了使用枚举的可能性。我可能会声明一个具有单个值的枚举,例如

enum E
{
  only_value // BUT IS IT??
}; 
Run Code Online (Sandbox Code Playgroud)

但似乎该标准规定,适合包含声明值的“最小位字段”的所有基础类型的值都是有效的。

来自cppreference.com

(如果源值是浮点型,则转换为枚举的基础类型,如果它适合足够大以容纳目标枚举的所有枚举器的最小位字段,则源值在范围内。)

如果您声明一个仅包含一个枚举器的枚举,则它的最小值可以是一位。按照该逻辑,具有该位的其他值的未命名枚举器应该是合法的。如果枚举基于有符号整数,则-10始终合法。对于无符号整数,01总是合法的。

标准中是否还有其他内容使未命名的位值非法或 UB?

Igo*_*nik 5

看起来enum E { value = 0; }只有一个值,即 0。标准是这样说的:

\n
\n

[dcl.enum]/8 ...否则[如果基础类型不固定 - IT],对于e min是最小枚举器且e max是最大枚举器的枚举,枚举的值是范围b minb max,定义如下:对于二进制补码表示,令K为 1;对于一个补码或符号数值表示,令 K 为 0。b max是大于或等于max(|e min | \xe2\x88\x92 K, |e maxn |)且等于2 M \xe2\x88\x92 1 的最小值,其中M是非负数整数。如果e min非负,则b min为零,否则\xe2\x88\x92(b max + K)

\n
\n

e min == e max == 0时,根据我的计算,这个数学运算还会产生b min == b max == 0

\n

然而,在你抱有希望之前,请参阅脚注 96:

\n
\n
    \n
  1. 这组值用于定义枚举类型的升级和转换语义。它并不排除枚举类型的表达式具有超出此范围的值。
  2. \n
\n
\n

我必须承认,如何生成值超出范围的枚举类型表达式对我来说并不是很明显。至少,static_cast如果所转换的值超出范围,则枚举类型会表现出未定义的行为。

\n