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

Hec*_*tor 3 c++ c++11

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

enum A
{   a = 0xFFFFFFFF };

enum class B
{   b = 0xFFFFFFFF };
Run Code Online (Sandbox Code Playgroud)

我知道我可以用enum class B : unsigned int.但是为什么默认底层类型enum的默认底层类型是默认的底层类型enum class?应该有一个设计决定.


澄清 我忘了提到错误:

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

这表明默认的底层类型enum classsigned int默认类型enumis unsigned int.这个问题是关于标志部分.

tha*_*ang 6

枚举类也称为作用域枚举.

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

详情如下所示.当你做这样的事情:

enum MyEnumType {
   Value1, Value2, Value3
 };
Run Code Online (Sandbox Code Playgroud)

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

enum MyEnumType2 {
   Value1, Value2, Value3, LastValue=0xffffff
 };
Run Code Online (Sandbox Code Playgroud)

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

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

 MyEnumType a = ...;
 fwrite(&a, sizeof(a), 1, fp);
Run Code Online (Sandbox Code Playgroud)

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

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

 enum class MyEnumType {
   ....
 }
Run Code Online (Sandbox Code Playgroud)

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

例如:

 enum class MyEnumType : char {
   ....
 }
Run Code Online (Sandbox Code Playgroud)

将基础类型更改为char.

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

  • 指定基础类型不限于作用域枚举。你可以对无作用域的做同样的事情。您 **可以** 说 `enum MyEnumType : int` 并获得一个具有固定基础类型的无作用域枚举。 (2认同)

小智 3

就N4140而言,MSVC是正确的:

\n\n
\n

\xc2\xa77.2/5 每个枚举都定义一个不同于所有其他类型的类型。每个枚举还有一个基础类型。可以使用enum-base显式指定基础类型。对于作用域枚举类型,int如果未显式指定,则为基础类型。[...]

\n
\n\n

有关基本原理,您可以阅读题为Strongly Typed Enums (Revision 3) N2347的提案。即,第2.2.2 节可预测/可指定类型(尤其是符号性)解释了 的底层类型enum是实现定义的。再次以N4140为例:

\n\n
\n

\xc2\xa77.2/7 对于基础类型不固定的枚举,\n 基础类型是一个整型,可以表示该枚举中定义的所有\n 枚举数值。如果没有整型类型可以表示所有枚举数值,则该枚举是格式错误的。使用哪个整型作为基础类型是由实现定义的,除非基础类型不得大于除非int枚举数的值无法放入 orintunsigned int。如果枚举器列表为空,则基础类型\n 就好像枚举具有值为 的单个枚举器0

\n
\n\n

以及N2347提出的解决方案:

\n\n
\n

该提案分为两部分,遵循专家工作组迄今为止的指示:

\n\n

\xe2\x80\xa2 提供了一个独特的新枚举类型,具有所有被认为需要的功能:

\n\n
\n

o 枚举数在其枚举范围内

\n\n

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

\n\n

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

\n
\n\n

\xe2\x80\xa2 为普通枚举提供纯向后兼容的扩展,\n 具有这些功能的子集

\n\n
\n

o 指定底层类型的能力

\n\n

o 使用枚举名称限定枚举器的能力

\n
\n\n

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

\n
\n\n

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

\n