C++11中的“枚举类型”(17.5.2.1.2)

10

C++11标准(17.5.2.1.2枚举类型)中的一句话:

1 在第27条款中定义的几种类型是枚举类型。每个枚举类型可以被实现为一个枚举或作为一个枚举的同义词(例如,一个带有常量整数值的整数类型(3.9.1))。

2 名为enumerated的枚举类型可以写成:

enum enumerated { V0 , V1 , V2 , V3 , ..... };
static const enumerated C0 (V0 );
static const enumerated C1 (V1 );
static const enumerated C2 (V2 );
static const enumerated C3 (V3 );
.....

3 这里,名称C0,C1等表示特定枚举类型的“枚举元素”。所有这些元素都具有不同的值。

这样的“枚举类型”之一是来自ios_base类(27.5.3类ios_base)的“seekdir”:

// 27.5.3.1.5 seekdir
typedef T4 seekdir;
static constexpr fmtflags beg = unspecified ;
static constexpr fmtflags cur = unspecified ;
static constexpr fmtflags end = unspecified ;

and

27.5.3.1.5 类型 ios_base::seekdir [ios::seekdir]

typedef T4 seekdir;

1 类型 seekdir 是一个枚举类型 (17.5.2.1.2),其中包含表126中指定的元素。

因此,那些静态 const 和 constexpr 成员所必需的惟一原因是因为“枚举类型”允许实现为整数类型(即当枚举为 int 时,我们需要定义常量代替枚举值),对吗?

问题1。如果库供应商决定将 seekdir 实现为枚举类型,他是否仍需要为枚举值定义静态常量?

问题2。为什么“枚举类型”首先允许实现为整数类型?也就是说,当枚举实现(在 C++11 中,枚举可以具有任何基础整数类型)没有这些静态常量成员时,可能比整数类型实现更差吗?


1
奖励问题:为什么在ios_base的概要中说“static constexpr fmtflags beg = unspecified;”而不是“static constexpr seekdir beg = unspecified;”? - 我刚刚向标准委员会报告了这个错别字。 - Daniel Frey
@Daniel“向标准团队报告了这件事”-很酷,你是怎么做到的? :) 另外,说实话,即使我复制粘贴了那个引用,我自己也没有注意到那个错别字。 - PowerGamer
我写了一封电子邮件发送到标准封面上提供的地址。我想这应该足够解决这种明显的打字错误了。通常,您应该遵循这些指南。 (http://isocpp.org/std/submit-a-library-issue) - Daniel Frey
@DanielFrey - 标准封面上没有电子邮件地址。我猜你指的是你用作实际标准替代品的草案。 - Pete Becker
@PeteBecker:哎呀,正确的 :) - Daniel Frey
2个回答

6
当这个标准被写时,强类型枚举并不存在,而普通的enum存在一个问题,即它们的内部类型未指定,并且可能会根据编译器开关而更改
对于seekdir,它可以是intbyte(仅作为示例),两者都是有效的表示。 GCC有一个命令行选项(--short-enums-fshort-enums)来解决此问题,默认情况下,它将使用int用作所有enum的最小类型,但使用该选项时,它将使用可以包含所有值的最小类型。
这意味着如果在函数签名中使用了真正的enum,则符号可能会更改,您需要重新编译所有东西。这就是为什么标准允许其他选项,以及为什么标准库实现具有控制类型的重要性,这也是为什么可以求助于特定的整数类型的原因。

@Daniel,您是否暗示在C++11之前的某个时候,GCC中的标准库实现会使用整数类型而不是枚举类型用于seekdir,因为您所描述的问题? - PowerGamer
@PowerGamer,在GCC的特定情况下,不,seekdir一直是enum _Ios_Seekdir的typedef,就我所知。 - Jonathan Wakely
@PowerGamer:我并没有暗示任何具体的事情,因为每个编译器和标准库都可以找到其他处理方式。在libstdc++的情况下,我认为这就是在ios_base.h中使用_S_ios_seekdir_end = 1L << 16的原因,这样它就永远不会被缩小到比int更小的任何东西,即使使用了-fshort-enums - Daniel Frey
@DanielFrey,既然像 _S_ios_seekdir_end = 1L << 16 这样的小技巧可以解决“重新编译所有内容”的需求,那么你在回答中所描述的并不能算作整数类型优于枚举类型(即使是 C++11 之前的枚举类型)的优点。我会接受 Pete 的答案(但无论如何感谢您的贡献)。 - PowerGamer
@PowerGamer:好的,我明白我的措辞有点过于强烈了,我已经修改了。请注意,我试图回答标准为什么允许这样做,而不是是否真的需要这样做。 - Daniel Frey

3

要求枚举类型的值为对象的原始原因是为了您可以获取它们的地址。这总是让我感到愚蠢,但在标准化的早期阶段存在着相当多的过度设计。


有趣的是,我甚至在我的答案中包含了它,并将其编辑掉了,因为我无法想出一个可能有用的例子 :) - Daniel Frey
@Pete,所以在C++11中允许"枚举类型"使用整数类型,并要求静态const类成员只是另一个向后兼容的情况吗?即使供应商决定使用例如"enum seekdir: int",他仍然需要定义这些静态constexpr成员吗? - PowerGamer
@PowerGamer,是的,标准要求实现定义具有地址的命名对象,它不能仅定义枚举器。 - Jonathan Wakely

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接