空的、未命名的枚举说明符的合法性

Legality of empty, unnamed enumeration specifier

在 §7.5 (C++14) 的示例中发现:

enum {}; // ill-formed

但是,从技术上讲,我认为代码是有效的。enum {} 是一个 enum-specifier,因此,它是一个 type-说明符,这是一个声明说明符,因此,它是一个简单声明,省略了init-declarator-list。这被 §7.5 接受。请注意,标识符 对于无范围枚举是可选的。此外,clang 会在编译时发出警告。

编辑

关于提到 the *decl-specifier-seq* shall introduce one or more names into the program, or shall redeclare a name introduced by a previous declaration 的答案,我在下面显示了一个编译的 typedef 声明,但其 decl-specifier-seq 没有在声明中引入任何名称:

typedef class {} A;

标准中明确规定(7 项声明)

  1. ...In such cases, and except for the declaration of an unnamed bit-field (9.6), the decl-specifier-seq shall introduce one or more names into the program, or shall redeclare a name introduced by a previous declaration.

这个声明

enum {};   // ill-formed 

不满足要求。它没有在程序中引入任何名称。

至于 typedef(s) 那么

7.1.3 The typedef specifier 1 Declarations containing the decl-specifier typedef declare identifiers that can be used later for naming 94)

在 C++14 FD 中,就在您的示例上方,解释了声明格式错误的原因:

In a simple-declaration, the optional init-declarator-list can be omitted only when declaring a class (Clause 9) or enumeration (7.2) […]

In such cases, the decl-specifier-seq shall introduce one or more names into the program, or shall redeclare a name introduced by a previous declaration.

因此

enum {} e;
enum {a};

Are valid - 我们的引用不适用于第一个声明,因为它包含一个 init-declarator,第二个引入名称 a作为调查员。请注意,GCC 不会编译第一个声明,这可能是一个错误。

你也提到了这句话

If the enumerator-list is empty, the underlying type is as if the enumeration had a single enumerator with value 0.

这是关于基础类型的声明,而不是枚举本身,因此与此事无关。


为什么typedef class {} A;编译?

A 是一个 init-declarator。是的,它是 - [dcl.dcl]/9:

If the decl-specifier-seq contains the typedef specifier, the declaration is called a typedef declaration and the name of each init-declarator is declared to be a typedef-name

即根据此定义,声明为 typedef-names 的名称是 init-declarators。因此有一个 init-declarator-list,我们上面的引用不适用。

如果您仔细阅读该标准,您会发现很多在纯句法层面上可以接受但被文本禁止的内容。这只是该基本思想的众多实例之一。

其中许多情况都非常明显。让我们考虑一个非常微不足道的问题:浮点数。使用类似于标准的语法符号,我们可以得到如下内容:

"-"-"opt位数opt "."."opt位数opt ("e""-"opt位数)opt

应有尽有"optional"。然而,这并不意味着虚无应该被视为一个数字。这也不意味着(例如).e 是有效的浮点数。这确实意味着如果存在其他一些,则几乎可以省略任何单独的部分。您不需要小数点后 之前的数字,因此每个数字本身都是可选的——但其中一个必须存在,因此 1..1 都有效,但只有 . 无效。同样,. 也是可选的——像 1e50 这样的东西是一个完全有效的浮点文字,即使它在任何地方都不包含 .

这些限制在与语法符号本身相关的文本中表达。允许(或不允许)的内容必须基于所有内容,而不仅仅是孤立的一件。