Hol*_*Cat 21 c++ language-lawyer
请考虑以下代码:( Ideone)
struct S
{
int a() {return 0;}
decltype(a()) b() {return 1;}
};
Run Code Online (Sandbox Code Playgroud)
它给了我以下错误:
错误:无法在没有对象的情况下调用成员函数'int S :: a()'
另一方面,这段代码很好编译:( Ideone)
struct S
{
int a() {return 0;}
auto b() -> decltype(a()) {return 1;}
};
Run Code Online (Sandbox Code Playgroud)
为什么一个例子有效,但另一个例子无法编译?
两个示例中的编译器行为是否完全正确?
如果编译器是正确的,那么为什么标准要求这种奇怪的行为呢?
Bri*_*ian 18
由于a是非静态成员函数,因此a()被解释为(*this).a().引用部分来自[expr.prim.general]/3,
如果声明声明了类的成员函数或成员函数模板
X,则表达式this是可选的cv-qualifer-seq和函数定义的结尾 之间的"指向cv-qualifier-seq的 指针"的prvalue ,成员 -声明者或声明者.它不应出现在可选的cv-qualifier-seq之前 ,它不应出现在静态成员函数的声明中(尽管它的类型和值类别是在静态成员函数中定义的,因为它们在非静态成员函数中) .X
该尾随收益型配备可选的后CV-预选赛-SEQ(在你的例子省略,因为S::b不是CV-合格),这样this就可能会出现,但不能出庭.
T.C*_*.C. 10
@Brian答案的一些补充:
在第一个例子中,a()是不转化成(*this).a().该转换在[class.mfct.non-static]/3中指定,并且仅在" this可以使用的上下文中"发生.如果没有这种转换,代码就会因为违反[expr.prim.id]/2而形成错误:
只能使用表示非静态数据成员或类的非静态成员函数的id表达式:
作为类成员访问([expr.ref])的一部分,其中对象表达式引用成员的类63或从该类派生的类,或者
形成指向成员的指针([expr.unary.op]),或
如果该id-expression表示非静态数据成员,则它出现在未评估的操作数中.
通过在允许的上下文之外使用表示非静态成员函数的id-expression a.
转换为类成员访问的事实并不重要,因为它使以下代码有效:
struct A {
int a;
decltype(a) b();
};
Run Code Online (Sandbox Code Playgroud)
如果将decltype(a)上述内容转换为decltype((*this).a),那么代码就会形成错误.
*this有一个特殊的豁免,通常的规则是类成员访问中的对象必须具有完整的类型([expr.prim.this]/2):
与其他上下文中的对象表达式不同
*this,为了成员函数体外部的类成员访问([expr.ref]),不需要它是完整类型.