在C ++标准的5.1.1 / 3中[expr.prim.general]
与其他上下文中的对象表达式不同,*为了达到目的,这不需要是完整类型 成员函数体外部的类成员访问权限。只有先前声明的班级成员 声明是可见的。
然后这个例子:
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());
你能解释一下这个引用和例子吗?究竟在这里展示了什么?
答案 0 :(得分:6)
这究竟是什么样的?在这里演示哪种陈述?
正在证明的陈述是:
与其他上下文中的对象表达式不同,*为了达到目的,这不需要是完整类型 成员函数体外的类成员访问权限(5.2.5)。
在成员函数的主体之外,有一个g()
的调用,这意味着this->g()
。在那里,*this
(即A
)的类型不完整。
根据C ++ 11标准的第9.2 / 2段:
在类说明符的结束
}
,类被视为完全定义的对象类型(3.9)(或完整类型)。 在类 member-specification 中,该类在函数体内被视为完整, 默认参数和非静态数据成员的括号或等号初始化程序(包括此类内容) 嵌套类)。否则,它在其自己的类 member-specification 中被视为不完整。
答案 1 :(得分:4)
这意味着您可以在类定义中的函数体外部通过this
显式或隐式地访问成员。此时,类型不完整,通常您无法访问不完整类型的成员。
但是你只能在成员函数声明的限制部分内做到这一点;关于this
:
它不会出现在可选的 cv-qualifier-seq
之前
意味着您不能在参数或前导返回类型规范中使用它。据我所知,在函数体外部,唯一可以使用它的地方是尾随返回类型。
在尾随返回类型中使用decltype
时,可能需要执行此操作,以获取涉及非静态成员的表达式类型。该示例通过隐式使用this
来访问尾随返回类型中的g()
来演示这一点。如果它被写成decltype(t + this->g())
,那将会更清楚地展示什么。
答案 2 :(得分:2)
首先,编译器会转换所有成员访问表达式:
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 [class.mfct.non-static] p3
[...]使用
(*this)
(9.3.2)将 id-expression 转换为类成员访问表达式(5.2.5)作为后缀 - 表达式位于.
运算符的左侧。 [...]
现在,标准中的示例在trailing-return-type中调用另一个成员函数体外的成员函数。那个电话也改变了:
template<class T> auto f(T t) -> decltype(t + (*this).g())
{ return t + (*this).g(); }
在成员函数体之外,*this
显然是不完整的类型。这意味着您只能访问在使用之前声明的名称 - 但该部分不仅适用于*this
用法:
struct X{
using typeA = int;
typeA f(); // OK, 'typeA' has been declared before
typeB g(); // Error: 'typeB' not declared before usage
using typeB = float;
};