问题:传递一个普通的lambda (到模板函数),它捕获this
并在没有明确的情况下调用this
的成员函数this->
无法在gcc上编译。如果lambda不是泛型的,或者lambda没有被传递给任何其他函数但是就地调用,它将编译为withoit this->
。在所有情况下,Clang对代码很酷。
另一轮 clang vs gcc 的时间。谁是对的?
template<typename TF>
void call(TF&& f)
{
f(1);
}
struct Example
{
void foo(int){ }
void bar()
{
call([this](auto x){ foo(x); });
}
};
int main()
{
Example{}.bar();
return 0;
}
bar()
= call([this](auto x){ foo(x); });
错误:无法调用成员函数'void Example :: foo(int)'没有对象 call([this](auto x){foo(x);});`
bar()
= call([this](auto x){ this->foo(x); });
bar()
= call([this](int x){ foo(x); });
bar()
= [this](auto x){ foo(x); }(1);
为什么this->
仅在通用lambda的情况下是必需的?
如果lambda未传递给this->
,为什么call
不必要?
谁不符合标准?
答案 0 :(得分:17)
这是一个gcc错误。来自[expr.prim.lambda]:
lambda-expression 的复合语句产生函数调用运算符的 function-body (8.4), 但出于名称查找(3.4)的目的,确定
this
(9.3.2)的类型和值并转换 id-expressions 使用(*this)
(9.3.1)将非静态类成员引用到类成员访问表达式中,复合语句在 lambda-expression 的上下文中被考虑EM>。 [例如:struct S1 { int x, y; int operator()(int); void f() { [=]()->int { return operator()(this->x + y); // equivalent to S1::operator()(this->x + (*this).y) // this has type S1* }; } };
-end example]
由于在您的示例中捕获了this
,因此名称查找应包含Example
的类成员,因此应找到Example::foo
。执行的查找与foo(x)
出现在 lambda-expression 本身的上下文中时会发生的情况相同,即代码如下所示:
void bar()
{
foo(x); // clearly Example::foo(x);
}
至少这个bug有一个非常简单的解决方法,如问题所示:只做this->foo(x);
。