C++ 为什么枚举类的默认类型与枚举的基础类型不同?

C++ 为什么枚举类的默认类型与枚举的基础类型不同?,c++,c++11,C++,C++11,我在问为什么以下代码在Visual Studio 2014 update 4中产生错误 enum A { a = 0xFFFFFFFF }; enum class B { b = 0xFFFFFFFF }; 我知道我可以使用枚举类B:unsigned int。但是为什么enum的默认底层类型与enum类的默认底层类型不同呢?应该有一个设计决策 澄清 我忘了提到错误: 错误C3434:枚举数值“4294967295”不能表示为“int”,值为“-1” 这表明default枚举类的底层

我在问为什么以下代码在Visual Studio 2014 update 4中产生错误

enum A
{   a = 0xFFFFFFFF };

enum class B
{   b = 0xFFFFFFFF };
我知道我可以使用
枚举类B:unsigned int
。但是为什么
enum
的默认底层类型与
enum类的默认底层类型不同呢?应该有一个设计决策


澄清 我忘了提到错误:

错误C3434:枚举数值“4294967295”不能表示为“int”,值为“-1”

这表明default枚举类的底层类型是
signed int
,而
enum
的默认类型是
unsigned int
。这个问题是关于符号部分的。

枚举类也称为作用域枚举

出于向后兼容性的原因,枚举非常必要。除其他原因外,还添加了作用域枚举(或枚举类),以确定枚举的基础类型

详情如下。当你这样做的时候:

enum MyEnumType {
   Value1, Value2, Value3
 };
 MyEnumType a = ...;
 fwrite(&a, sizeof(a), 1, fp);
编译器可以自由选择MyEnumType的底层数值类型,只要您的所有值都可以适合该类型。这意味着编译器可以自由选择char、short、int、long或其他数值类型作为MyEnumType的基础类型。经常使用的一种做法是向枚举中添加最后一个值,以强制基础类型的最小大小。例如:

enum MyEnumType2 {
   Value1, Value2, Value3, LastValue=0xffffff
 };
 enum class MyEnumType : char {
   ....
 }
保证基础类型的大小至少与无符号32位相同,但可以更大(例如,64位无符号)。编译器的这种灵活性是好是坏

这很好,因为您不必考虑底层类型。这是不好的,因为现在这是一个由编译器决定的不确定性,如果您确实考虑了底层类型,您就无能为力了。这意味着同一段代码在不同的编译器上可能意味着不同的内容,例如,如果您想执行以下操作,这可能是一个问题:

enum MyEnumType {
   Value1, Value2, Value3
 };
 MyEnumType a = ...;
 fwrite(&a, sizeof(a), 1, fp);
将枚举写入文件的位置。在这种情况下,切换编译器或向枚举添加新值可能会导致文件未对齐

新的作用域枚举解决了这个问题。为了做到这一点,在声明作用域枚举时,语言必须有一种方法来修复基础类型。因此,标准是:

 enum class MyEnumType {
   ....
 }
默认为int类型。通过从相应的数值类型派生枚举类,可以显式更改基础类型

例如:

enum MyEnumType2 {
   Value1, Value2, Value3, LastValue=0xffffff
 };
 enum class MyEnumType : char {
   ....
 }
将基础类型更改为char


因此,枚举的默认基础类型可能会根据枚举中的项目数量和分配给项目的文字值而更改。另一方面,枚举类的默认基础类型始终为int。

就N4140而言,MSVC是正确的:

§7.2/5每个枚举定义了不同于所有枚举的类型 其他类型。每个枚举也有一个基础类型。这个 可以使用枚举基显式指定基础类型。对于 作用域枚举类型,如果不是,则基础类型为
int
明确指定。[……]

关于理由,您可以阅读标题为的提案。也就是说,第2.2.2节可预测/可指定类型(特别是签名)解释了
enum
的底层类型是实现定义的。例如,N4140再次:

§7.2/7对于基础类型不固定的枚举 基础类型是可以表示所有 枚举中定义的枚举数值。如果没有整数类型,则可以 表示所有枚举数值,则枚举的格式不正确。信息技术 是否定义了将哪个整数类型用作 基础类型,但基础类型不得大于 小于
int
,除非枚举数的值不能放入
int
无符号整数
。如果枚举数列表为空,则基础类型 好像枚举有一个值为
0
的枚举数

N2347提出的解决方案:

本提案分为两部分,遵循迄今为止EWG的指示:

•提供一个独特的新枚举类型,该类型具有 认为可取的:

o枚举数在其枚举范围内

o枚举数和枚举不隐式转换为int

o枚举具有已定义的基础类型

•为具有 这些特征的子集

o指定基础类型的能力

o使用枚举名限定枚举数的能力

为独特的新枚举类型建议的语法和措辞如下 基于此功能的C++/CLI[C++/CLI]语法。提议的 现有枚举扩展的语法是为相似性而设计的


因此,他们采用了解决方案,为作用域枚举提供了一个定义的底层类型。

这就是标准所要求的。作用域枚举始终具有显式 基础类型,默认为
int
,除非您另有说明

至于动机:表面上,混为一谈是没有意义的 基础类型与枚举的作用域是否相同。我怀疑 这仅仅是因为作者希望始终能够 前向声明作用域枚举;至少在理论上,尺寸和 指向枚举的指针的表示形式可能取决于基础 类型。(标准将此类转发声明称为不透明枚举类型。)

不,我不认为这真的是一个混为一谈的正当理由 作用域和基础类型。但我不是整个委员会,而且 想必,大多数人对此事的感受与我不同。我看不见 亩