在§7.5(C ++ 14)的例子中,人们发现:
enum {}; // ill-formed
但是,从技术上讲,我认为代码是有效的。enum {}
是枚举说明符,因此,它是类型说明符,是一个 decl-specifier ,因此,它是一个 simple-declaration ,省略了 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;
答案 0 :(得分:7)
在C ++ 14 FD,正上方您的示例中,解释了为什么声明格式不正确:
在 simple-declaration 中,可选的 init-declarator-list 可以是 仅在声明类(第9条)或枚举(7.2)时省略 [...]
在这种情况下, decl-specifier-seq 应引入一个或多个 在程序中输入名称,或者重新声明由a引入的名称 先前的声明。
因此
enum {} e;
enum {a};
Are valid - 我们的引用不适用于第一个声明,因为它包含 init-declarator ,第二个引用名称a
作为枚举器。请注意,GCC不会编译第一个声明,这可能是一个错误。
您还提到了引用
如果枚举器列表为空,则基础类型就像是 枚举有一个值为
0
的枚举器。
这是关于基础类型的声明,而不是枚举本身,因此与此事无关。
typedef class {} A;
会编译? A
是 init-declarator 。是的,它是 - [dcl.dcl] / 9:
如果 decl-specifier-seq 包含 typedef说明符, 声明称为typedef声明和每个声明的名称 init-declarator 被声明为 typedef-name
即。根据此定义,声明为 typedef-names 的名称是 init-declarators 。因此,有一个 init-declarator-list ,我们的上述引用并不适用。
答案 1 :(得分:2)
标准中有明确的(7声明)
- ...在这种情况下,除了声明未命名的位域(9.6)之外,decl-specifier-seq 应引入一个或多个 名称进入程序,或者重新声明由a引入的名称 先前的声明。
醇>
此声明
enum {}; // ill-formed
不符合要求。它没有在程序中引入任何名称。
至于typedef然后
7.1.3 typedef说明符1包含可在以后使用的decl-specifier typedef声明标识符的声明 用于命名94)
答案 2 :(得分:2)
如果你仔细研究这个标准,你会发现很多东西会在纯粹的语法层面上被接受,但是被文本禁止。这只是该基本思想的许多实例之一。
其中许多情况非常明显。让我们考虑一个非常微不足道的问题:一个浮点数。使用类似于标准的句法符号,我们可以得到类似的东西:
" - " opt 数字 opt "。&# 34; opt 数字 opt (" e"" - &#34 ; opt 数字) opt
那里的一切都是"可选的"。然而,这并不意味着虚无应该被视为一个数字。也不意味着(例如).e
是有效的浮点数。这意味着如果存在其他一些,几乎任何单件都可以省略。你不需要在小数点之后的和之前的数字,所以每个都是可选的 - 但是必须存在一个或另一个,所以1.
和{{ 1}}都有效,但只有.1
不是。同样,.
也是可选的 - 类似.
的内容是完全有效的浮点文字,即使它在任何地方都不包含1e50
。
这些限制在与句法符号本身相关的文本中表达。允许(或不允许)的所有内容必须基于所有内容,而不仅仅是单独的内容。