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

时间:2015-02-22 15:49:05

标签: c++ c++11

我在问为什么以下代码会在Visual Studio 2014更新4中产生错误。

enum A
{   a = 0xFFFFFFFF };

enum class B
{   b = 0xFFFFFFFF };

我知道我可以使用enum class B : unsigned int。但为什么enum的默认基础类型与enum class的默认基础类型不同?应该有一个设计决定。


澄清 我忘了提到错误:

  

错误C3434:枚举值' 4294967295'不能表示为' int',值是' -1'

这表明enum class默认基础类型为signed intenum的默认类型为unsigned int。这个问题是关于标志部分的。

3 个答案:

答案 0 :(得分:6)

枚举类也称为范围枚举。

出于向后兼容性的原因,

枚举非常必要。除了其他原因之外,还添加了scoped enum(或枚举类)来确定枚举的基础类型。

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

enum MyEnumType {
   Value1, Value2, Value3
 };

只要您的所有值都适合该类型,编译器就可以自由选择MyEnumType的基础数字类型。这意味着编译器可以自由选择char,short,int,long或其他数字类型作为MyEnumType的基础类型。经常进行的一种做法是向枚举添加最后一个值以强制基础类型的最小大小。例如:

enum MyEnumType2 {
   Value1, Value2, Value3, LastValue=0xffffff
 };
保证

的底层类型至少与无符号32位一样大,但它可能更大(例如,64位无符号)。编译器的这种灵活性是好的和坏的。

这是好的,因为你不必考虑基础类型。这是不好的,因为现在这是一个由编译器决定的不确定性,如果你考虑底层类型,你就无法做任何事情。这意味着同一段代码在不同的编译器上可能意味着不同的东西,例如,如果你想做这样的事情,可能会出现问题:

 MyEnumType a = ...;
 fwrite(&a, sizeof(a), 1, fp);

将enum写入文件的位置。在这种情况下,切换编译器或向枚举添加新值可能导致文件未对齐。

新的范围枚举解决了这个问题。为此,当您声明作用域枚举时,语言必须有一种方法来修复基础类型。那么标准就是:

 enum class MyEnumType {
   ....
 }

默认为输入int。可以通过从适当的数字类型派生枚举类来显式更改基础类型。

例如:

 enum class MyEnumType : char {
   ....
 }

将基础类型更改为char。

因此,枚举的默认基础类型可以根据枚举中的项目分配的项目数和文字值进行更改。另一方面,枚举类的默认底层类型始终是int。

答案 1 :(得分:3)

就N4140而言,MSVC是正确的:

  

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

有关理由,您可以阅读标题为Strongly Typed Enums (Revision 3) N2347的提案。即, 2.2.2可预测/可指定类型(特别是签名)部分解释了enum的基础类型是实现定义的。例如,N4140:

  

§7.2/ 7对于其基础类型未修复的枚举,   底层类型是一个可以代表所有的整数类型   枚举中定义的枚举器值。如果没有整数类型可以   表示所有枚举器值,枚举是不正确的。它   是实现定义的,使用整数类型作为   基础类型,但基础类型不应该更大   除int之外,枚举者的值不能适合intunsigned int   0。如果枚举器列表为空,则为基础类型   就好像枚举有一个值为{{1}}的枚举器。

和N2347提出的解决方案:

  

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

     

•提供具有所有功能的独特新枚举类型   被认为是可取的:

     
    

o枚举数属于其枚举范围

         

o枚举器和枚举不会隐式转换为int

         

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

  
     

•为简单枚举提供纯粹的向后兼容扩展   这些功能的子集

     
    

o指定基础类型的能力

         

o使用枚举名称

来限定枚举数的能力   
     

针对不同的新枚举类型的建议语法和措辞是   基于此功能的C ++ / CLI [C ++ / CLI]语法。提议   现有枚举扩展的语法是为了相似而设计的。

所以他们选择了解决方案,为scoped enums提供了一个定义的底层类型。

答案 2 :(得分:1)

这就是标准所要求的。范围内的枚举总是有明确的 基础类型,除非另有说明,否则默认为int

至于动机:从表面上看,混淆是没有意义的 枚举是否有范围的基础类型。我猜测 这只是因为作者想要永远能够做到这一点 forward declare scoped enums;至少在理论上,尺寸和 指向枚举的指针的表示可能取决于底层 类型。 (标准称这种前向声明为不透明的枚举类型。)

不,我不认为这确实是混淆的正当理由 范围和基础类型。但我不是整个委员会,而且 据推测,大多数人并不觉得我这样做。我看不到 除非你是前锋,否则很多用于指定基础类型 宣布枚举;它没有任何其他帮助。我想要的地方 几乎到处都使用scoped enum我正在处理一个真实的 列举。 (当然,真正的枚举永远不会有价值观 哪个不适合int;那些真的只会在你使用时出现 用于定义位掩码的枚举。)