从通用 lambda 调用 `this` 成员函数 - clang vs gcc

Calling `this` member function from generic lambda - clang vs gcc

问题: 传递通用 lambda (到模板函数) 捕获 this 并调用的成员函数没有显式 this->this 不会在 gcc 上编译。如果 lambda 不是通用的,或者如果 lambda 没有传递给任何其他函数而是就地调用,它会在没有显式 this-> 的情况下进行编译。 Clang 在所有情况下都对代码很酷。

又一轮 clang vs gcc 的时间到了。谁是对的?

Wandbox example


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;
}





为什么只有在通用 lambda 的情况下才需要 this->

如果没有将 lambda 传递给 call,为什么 this-> 不是必需的?

谁不符合标准?

这是一个 gcc 错误。来自 [expr.prim.lambda]:

The lambda-expression’s compound-statement yields the function-body (8.4) of the function call operator, but for purposes of name lookup (3.4), determining the type and value of this (9.3.2) and transforming id-expressions referring to non-static class members into class member access expressions using (*this) (9.3.1), the compound-statement is considered in the context of the lambda-expression. [ Example:

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 的 class 成员,因此应该找到 Example::foo。执行的查找与 foo(x) 出现在 lambda 表达式 本身的上下文中时发生的查找相同,也就是说,如果代码看起来像:

void bar()
{
    foo(x); // clearly Example::foo(x);
}

至少这个错误有一个非常简单的解决方法,如问题中所示:只需执行 this->foo(x);