【问题标题】:According to my interpretation of §3.4.1/8 this code should compile. What am I missing?根据我对 §3.4.1/8 的解释,这段代码应该可以编译。我错过了什么?
【发布时间】:2015-07-16 14:50:20
【问题描述】:

根据来自N4140 的 [basic.lookup.unqual]/8,以下 sn-p 应该可以编译。但它不在clang、gcc 和 vs2013 中。

struct C {
    void f(I) {}
    using I = int;
};

[basic.lookup.unqual]/8(重点是我的):

对于类X的成员,成员函数体中使用的名称, 在默认参数中,在异常规范中,在 非静态数据成员 (9.2) 的 brace-or-equal-initializer,或在 X 定义之外的类成员定义中, 在成员的 declarator-id31 之后,应为 以下列方式之一声明:

  • 在其用于使用它的块或封闭块 (6.3) 之前,或
  • 应为X 类的成员X (10.2) 基类的成员,或
  • ...

31) 即,例如,出现在 parameter-declaration-clause异常规范.

【问题讨论】:

  • 在我看来 a name used in a member function body, in a default argument, in an exception-specification, in the brace-or-equal-initializer of a non-static data member (9.2), or in the definition of a class member outside of the definition of X 不适用于 I。它不在函数体中,它是一个参数,但不是默认的,它与异常或初始化无关,它不在X的定义之外...
  • 该名称根本不在范围内,因此您无法在成员函数声明器中引用它。引用的文本不会改变这一点。

标签: c++ language-lawyer c++14


【解决方案1】:

你使用它的方式不属于[basic.lookup.unqual]/8中的任何一个条件,它没有被使用:

  • 在成员函数体中
  • 在默认参数中
  • 在异常规范中
  • 在非静态数据成员的大括号或等号初始化器中

也不属于这种情况:

在 X 的定义之外定义一个类成员

以下示例显示了一些确实遵循这些规则的案例:

struct C {
    int y = I() ;           // brace-or-equal-initializer of non-static data member
    void f(int x = I())     // default argument
      noexcept(sizeof(I)<4) // exception-specification
    {
          I i = x ;         // member function body
    }
    using I = int;   
};

【讨论】:

  • 脚注 31 怎么样?
  • 脚注不规范。
  • @JonathanWakely 这甚至不相关,因为脚注对应的文本不适用于此处。
  • 脚注 31 清楚地表明“遵循成员的 declarator-id”意味着它仅适用于参数或 noexcept 子句中使用的名称。它基本上排除了声明符ID之前的返回值。
  • @R.MartinhoFernandes 脚注 31 说得很清楚 name that occurs, for instance, in a **type** in the *parameter-declaration-clause*
【解决方案2】:

[…] 或在类成员的定义中在定义之外X,跟随成员的declarator-id

即以下是有效的

struct C {
    using I = int;
    void f(I);
};

void C::f(I) {}

【讨论】:

  • 你的 sn-p 应该和我的一样。 AFAICT,这一段基本上说成员函数总是在其类定义之后被解析,即使是内联定义的。
  • 它的哪一部分是这样说的? Columbo 引用的那句话本质上是说,该规则适用的其中一件事是适用于类外定义。你从哪里读到所有成员定义都是类外的?
  • @R.MartinhoFernandes 请参阅 James McNellis 的 answer
  • 我深信不疑,特别是因为这个 sn-p 不能(也不能)编译:struct C{ void f(I); using I = int; }; void C::f(I) {}。 (+1)
猜你喜欢
  • 1970-01-01
  • 2015-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-06
  • 1970-01-01
  • 2011-08-20
相关资源
最近更新 更多