`*这个“外部成员”功能体? 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;
};