空的、未命名的枚举说明符的合法性
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 项声明)
- ...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
这样的东西是一个完全有效的浮点文字,即使它在任何地方都不包含 .
。
这些限制在与语法符号本身相关的文本中表达。允许(或不允许)的内容必须基于所有内容,而不仅仅是孤立的一件。
在 §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 项声明)
- ...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
这样的东西是一个完全有效的浮点文字,即使它在任何地方都不包含 .
。
这些限制在与语法符号本身相关的文本中表达。允许(或不允许)的内容必须基于所有内容,而不仅仅是孤立的一件。