【问题标题】:Why must an enumeration's size be provided when it is forward declared?为什么在前向声明时必须提供枚举的大小?
【发布时间】:2015-03-13 14:46:35
【问题描述】:

我只是不明白为什么枚举的大小与编译器相关,而类的大小却不相关。

我的代码示例:

class A;
enum E;   // must be enum E : int; in order to compile 

void f(const A & param);
void f(const E & param);

我在这里谈论的是标准 C++ 编译器。 我知道 MSVC 让它编译并且工作正常。所以问题是:

为什么这还没有标准化?

【问题讨论】:

  • 它比你想象的还要混乱:我认为 msvc 将未调整大小的枚举强制为 32 位。
  • @Yakk 我也这么认为。但是为什么尺寸还是要相关的呢?
  • 我不确定它的大小是否相关,而是显然不是 C++03 语法。您可以使用范围枚举,而不是大小,使用关键字 struct 或 class 之一。相关标准:“声明无范围枚举的不透明枚举声明不得省略枚举基数。”
  • 不确定是否相关,但在我的关联电路中确实发生了标准不允许的唯一情况,是迄今为止的现有实践(主要作为 Visual C++ 语言扩展)。所以,也许是政治。
  • 我对阅读有关标准化的内容有非常模糊的记忆。它基本上是编译器编写者容易做的事情。即,enum class X:type;enum class X:type { values... }; 是容易实现的目标(易于实施且有用)。您所描述的可能并不那么容易(因为我们现在有一个编译器有一个不知道大小的枚举,这在更改之前是不可能的)。我对这段记忆没有信心。

标签: c++ c++11 enums forward-declaration


【解决方案1】:

这已经标准化,proposal 2764: Forward declaration of enumerations (rev. 3) 允许在指定基础类型的情况下前向声明枚举,而在此之前这是不可能的。

主要原因是,当未指定基础类型时,大小是实现定义的,并且可能取决于枚举器值。来自草案 C++11 标准部分7.2[dcl.enum]

对于底层类型不固定的枚举,底层 type 是一个整数类型,可以表示所有枚举数值 在枚举中定义。如果没有整数类型可以代表所有 枚举值,枚举格式不正确。它是 实现定义使用哪种整数类型作为底层 类型,但基础类型不得大于 int 除非枚举器的值不能放入 int 或 unsigned 诠释。如果 enumerator-list 为空,则基础类型就像 枚举有一个值为 0 的枚举数。

当按值传递时,不知道底层类型是一个问题是有道理的,但是当它是指针或引用时为什么它是一个问题?这很重要,因为显然在某些架构上,char*int* 可以具有不同的大小,如 comp.lang.c++ discussion: GCC and forward declaration of enum:

中所述

[...] 虽然在大多数架构上这可能不是问题,但在某些架构上 体系结构指针将具有不同的大小,以防万一 字符指针。所以最后我们想象中的编译器不知道 放什么来获得 ColorsEnum*[...]

我们有以下 stackoverflow 答案供参考,它描述了 char* can be larger than int* 的情况,它支持上述讨论中的断言。

一些more details on the possible sizes of pointers 看起来char *void * 是这里的两个主要例外,因此其他对象指针不应该有同样的问题。所以看起来这种情况最终是枚举独有的。

【讨论】:

【解决方案2】:

这是设计目标的不同。

向前声明一个类会创建一个不完整的类型,可以在指针/引用中不透明地使用。这是一个非常有用的属性。

不完整的枚举类型没有那么有用。然而,能够声明一个枚举而不声明枚举中的常量是 有用的。可以通过要求必须指定大小来避免来自不完整枚举类型的复杂性。

所以我最好的猜测是,在设计此功能时,编译器实现者被牢记在心,委员会发现不完整枚举增加的复杂性不值得获得好处。

【讨论】:

  • “通过要求必须指定大小,可以避免来自不完整枚举类型的复杂性。”可能是这样(尽管我对此表示怀疑)但完全无关紧要,因为不需要指定尺寸。要求是枚举类型要么是范围内的,要么具有指定的大小,或两者兼而有之。
  • @Cheersandhth.-Alf 我显然是指在无法推断时指定大小。范围枚举类型的默认大小为int
  • 如果你想要一个指向枚举的指针怎么办?还是参考?这根本不需要任何大小信息,只需要名称引用类型这一事实。
  • @Yakk 我的回答解释了这一点。它不是那么有用,而且会使编译器复杂化。
  • @orlp:我不明白为什么标准不能只要求例如int 前向声明的非范围非大小 enum 的大小(即经典的enum),或者确实为什么不完整的类型应该是一个问题(它已经被处理了,例如它不会阻止使用 by- 的原型功能值参数,仅此而已)。我认为这意味着你的论点不成立。但后来我写的也不太对。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-20
  • 2010-09-09
相关资源
最近更新 更多