`*这个“外部成员”功能体? 5.1.3的C++标准[ExPR.Prim.Prim]

`*这个“外部成员”功能体? 5.1.3的C++标准[ExPR.Prim.Prim] ,c++,c++11,C++,C++11,与其他上下文中的对象表达式不同,*出于某种目的,它不需要是完整类型 成员函数体外部的类成员访问权限。只有类成员声明优先 对声明的修改是可见的 然后这个例子: struct A { char g(); template<class T> auto f(T t) -> decltype(t + g()) { return t + g(); } }; template auto A::f(int t) -> decltype(t + g()); 结构

与其他上下文中的对象表达式不同,*出于某种目的,它不需要是完整类型 成员函数体外部的类成员访问权限。只有类成员声明优先 对声明的修改是可见的

然后这个例子:

struct A {
    char g();
    template<class T> auto f(T t) -> decltype(t + g()) 
    { return t + g(); }
};
template auto A::f(int t) -> decltype(t + g());
结构A{ charg(); 模板自动f(T)->decltype(T+g()) {返回t+g();} }; 模板自动A::f(int t)->decltype(t+g()); 你能解释一下这个引语和例子吗?这里到底演示了什么

这究竟是一个什么样的例子?这里演示的是哪种说法

所证明的说法是:

与其他上下文中的对象表达式不同,*出于某种目的,它不需要是完整类型 成员功能体外部的类成员访问权限(5.2.5)

在成员函数的主体之外,有一个对
g()
的调用,这意味着
this->g()
。此处,
*此
(即
A
)的类型不完整

根据C++11标准第9.2/2段:

在类说明符的结尾处,类被视为完全定义的对象类型(3.9)(或完全类型)。 在类成员规范中,类在函数体中被认为是完整的, 默认参数,以及非静态数据成员的大括号或相等初始值设定项(包括 嵌套类)。否则,在其自身的类成员规范中,它被视为不完整的


这意味着您可以通过类定义中的函数体之外的
this
显式或隐式访问成员。此时,类型是不完整的,通常您无法访问不完整类型的成员

但您只能在成员函数声明的受限部分内执行此操作;上一句话是关于这个:

它不应出现在可选cv限定符seq之前

这意味着您不能在参数或前导返回类型规范中使用它。就我所见,在函数体之外,唯一可以使用它的地方是尾部返回类型


在尾部返回类型中使用
decltype
时,可能需要执行此操作,以获取包含非静态成员的表达式的类型。该示例通过隐式使用
this
访问尾部返回类型中的
g()
来演示这一点。如果将其编写为
decltype(t+this->g())

首先,所有成员访问表达式都由编译器转换:

struct X{
  int a;
  void f(){}
  void g(int b){
    int x = a + b; // actually: int x = (*this).a + b
    f(); // actually: (*this).f();
  }
};
§9.3.1[类mfct非静态]p3

[…]使用
(*this)
(9.3.2)作为
操作符左侧的后缀表达式,将id表达式转换为类成员访问表达式(5.2.5)。[……]

现在,来自标准的示例调用另一个成员函数体外部的成员函数,返回类型为尾部。这一呼吁也发生了转变:

template<class T> auto f(T t) -> decltype(t + (*this).g()) 
{ return t + (*this).g(); }

我认为它指的是
A::g
f
签名中的用法,而不是它的主体。对于编译器编写人员来说,这会使事情变得复杂,因为您被要求(可能)在
g()
上执行重载解析,因此要考虑
A::g
,即使
A
没有完全定义。在此之前,典型的做法是首先解析所有声明(方法和成员),然后使用“完全定义的”
a
解析方法体。@MatthieuM.:注意它在函数体之外。您仍然必须将内联函数体的解析推迟到解析类说明符之后。是的,并且
尾部返回类型不在该列表中。@user1131467:对,因此在执行
this->g()
时它是不完整的。这是唯一的应用程序吗<在
尾随返回类型中的code>decltype
?(或者我猜在参数声明中也是如此)@user1131467:我不知道。这是我能马上想到的唯一一个,但我在周一的时候不是很有想象力。@user1131467:不一定是尾随返回类型。您可以使用
decltype(this)
,即使返回类型不是尾随类型,也可以在参数中使用declaration@AndyProwl:我认为只能在类说明符中使用
decltype(this)
非尾随内联。在名称空间范围内,解析器还不知道它在哪个类中。@AndyProwl:实际上你不能;前面的句子阻止您使用
this
,除非在尾部返回类型中。(“它不应出现在可选cv限定符seq之前,其中“It”表示
this
)。我认为它在类说明符内
A::f
的内联定义中是不完整的,但是我认为它在右括号后的
A::f
声明中是完整的。在成员函数定义的主体内,
*此
始终被视为完整类型,请参见
§9.2/2
。是的,但尾部返回类型不是函数体的一部分。呃,是的,正如我所说,
*此
在尾部返回类型中是不完整的(我将其表述为“函数体外部”)。对,但是在类说明符的右括号后面的函数声明的尾部返回类型中(在它的外部)
*这是完整的。
struct X{
  using typeA = int;
  typeA f(); // OK, 'typeA' has been declared before

  typeB g(); // Error: 'typeB' not declared before usage
  using typeB = float;
};