【问题标题】:Why class { int i; }; is not fully standard-conformant?为什么类 { int i; };不完全符合标准?
【发布时间】:2012-10-19 18:28:13
【问题描述】:

这是一个后续问题。

previous question 中,@JohannesSchaub-litb 表示以下代码完全符合标准:

class { int i; };  //unnamed-class definition. § 9/1 allows this!

然后他补充说,

虽然它在语法上是有效的,但它打破了这样的类必须在其封闭范围内声明至少一个名称的规则。

我真的无法理解这一点。他在说什么名字?

谁能进一步详细说明(最好引用标准)?

【问题讨论】:

  • 他在说什么名字? 不存在的那个。该声明没有声明类名,也没有声明 typedef 名称或变量/函数——没有任何内容添加到声明出现的范围内。
  • 相当于写法:"int;"作为一行代码。它命名了一个类型,但没有给它一个名字。

标签: c++ class definition identifier standards-compliance


【解决方案1】:

关键是通过声明class{ int i; };,您正在组装一堆符号(在本例中为int i),您将无法在任何代码中的其他任何地方使用。

要使这段代码有意义,您至少应该执行以下操作之一:

class Myclass { int i; }; //I can furthermore instantiate variables of Myclass
class { int i; } myvar; //This in fact creates a myvar object
typedef class { int i; } MyType; //I can funthermore instantiate variables of MyType

只要说class{ int i; };,你就是在对编译器说:

  • 保留int 并将其命名为i
  • 将其包装成 class 我永远不会打电话...
  • 算了! (};)

如果您从程序中删除该声明,一切都不会改变。

【讨论】:

  • 这很好,但恕我直言,它需要明确同意或不同意“此代码不符合标准”。
  • 显然类声明是没有用的,但这并不能回答是否允许的问题。标准允许有许多无用的结构。为什么它得到这么多赞?
  • OP 要求解释,而不是协议(他说“可能”......)根据标准,每个声明都必须声明一些东西。所提议的没有任何声明。我可以理解“无”可以被视为特定的“某事”,但这是不允许的诡辩(编译器假设“一定有什么东西被遗忘了”,这可能很危险)
  • @Griwes:也许你应该根据这是否回答了问题来投票。
  • @interjay,我投了赞成票。并写“+1”,如“好人”,而不是“我支持你”。我确实区分“+1”和“Upvote”。
【解决方案2】:

来自 GCC 的错误信息解释得很简洁:

$ cat > a.cc
class { int i; };
$ g++ -Wall -std=c++98 a.cc
a.cc:1: error: abstract declarator ‘<anonymous class>’ used as declaration

class { int i; }abstract-declarator(标准,§8),但不是有效的声明(§7)。这就是@JohannesSchaub-litb 引用的规则:对于有效的声明,您需要声明一些内容,例如类名或变量名。

【讨论】:

    【解决方案3】:

    你打破了[basic.scope.pdecl]/6,上面写着:

    在详细类型说明符中首先声明的类的声明点如下:
    — 表格声明
    class-key attribute-specifier-seqopt identifier ;

    标识符被声明为包含声明的范围内的类名,否则
    — 对于形式的详细类型说明符
    class-key identifier

    如果在 decl-specifier-seq 或 parameter-declaration-clause 中使用了详细类型说明符 在命名空间范围内定义的函数,标识符被声明为命名空间中的类名 包含声明;否则,除了作为友元声明外,标识符在 包含声明的最小命名空间或块范围。 [注:这些规则也适用于 模板。 —尾注] [注:其他形式的详细类型说明符不声明新名称, 因此必须引用现有的类型名称。见 3.4.4 和 7.1.6.3。 ——尾注]

    1. 您没有创建匿名类型的变量
    2. 你没有创建类型

    标准中的另一个示例([basic.def]/2)证明您的示例不符合标准:

    struct S { int a; int b; };       // defines S, S::a, and S::b
    struct X {                        // defines X
      int x;                          // defines non-static data member x
      static int y;                   // declares static data member y
      X(): x(0) { }                   // defines a constructor of X
    };
    int X::y = 1;                     // defines X::y
    enum { up, down };                // defines up and down
    namespace N { int d; }            // defines N and N::d
    namespace N1 = N;                 // defines N1
    X anX;                            // defines anX
    

    你的例子没有定义任何东西(除了匿名结构,谁的字段不能被访问)。

    注意枚举的一个例外,因为这种情况引入了两个要使用的值。

    【讨论】:

      【解决方案4】:

      class { int i; }; 不是一个有效的声明,因为它是一个没有 init-declarator-listsimple-declaration 但它没有引入(或重新声明) 类名。

      ISO/IEC 14882:2011 7 [dcl.dcl] / 3:

      simple-declaration 中,可选的 init-declarator-list 只有在声明类(第 9 条)或枚举(7.2)时才能省略,即, 当 decl-specifier-seq 包含一个 class-specifier,一个 elaboratedtype-specifier 和一个 class-key em> (9.1) 或 枚举说明符。在这些情况下,只要 class-specifierenum-specifier 出现在 decl-specifier-seq 中,这些说明符中的标识符就是在声明所声明的名称中(如 class-namesenum-namesenumerators,具体取决于语法)。 在这种情况下,除了声明未命名的位域 (9.6),decl-specifier-seq 应在程序中引入一个或多个名称,或重新声明一个名称由先前的声明引入。

      【讨论】:

        【解决方案5】:

        标准的第 9 条允许 class {public: int i;}(注意缺少最后一个分号),因为这个用于未命名类的 decl-specifier-seq 可能用于其他一些构造,例如 typedef或变量声明。 class {public: int i;}; 的问题(注意最后的分号现在存在)是这个类规范现在变成了一个声明。这是标准第 7 条第 3 款的非法声明:

        在这种情况下,除了声明未命名的位域 (9.6),decl-specifier-seq 应在程序中引入一个或多个名称,或重新声明一个名称由先前的声明引入。

        【讨论】:

        • +1 用于在 decl-specifier-seqdeclaration 之间进行澄清。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-10-13
        • 1970-01-01
        • 2017-05-27
        • 2011-01-19
        • 1970-01-01
        • 2010-09-05
        相关资源
        最近更新 更多