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

Posted

技术标签:

【中文标题】从通用 lambda 调用 `this` 成员函数 - clang vs gcc【英文标题】:Calling `this` member function from generic lambda - clang vs gcc 【发布时间】:2015-11-12 21:16:19 【问题描述】:

问题:传递一个通用 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;


bar() = call([this](auto x) foo(x); ); clang++ 3.6+ 编译。 g++ 5.2+ 无法编译。

错误:不能在没有对象的情况下调用成员函数 'void Example::foo(int)' 调用([this](auto x) foo(x); );`


bar() = call([this](auto x) this-&gt;foo(x); ); clang++ 3.6+ 编译。 g++ 5.2+ 编译。
bar() = call([this](int x) foo(x); ); clang++ 3.6+ 编译。 g++ 5.2+ 编译。
bar() = [this](auto x) foo(x); (1); clang++ 3.6+ 编译。 g++ 5.2+ 编译。

为什么this-&gt; 仅在通用 lambda 的情况下是必需的?

如果没有将 lambda 传递给 call,为什么不需要 this-&gt;

谁不符合标准?

【问题讨论】:

你注意到的不一致表明clang在这里是正确的。 甚至不用看标准,我可以绝对肯定地说 Clang 是对的。即使不符合标准,也还是对的;在那种情况下,标准是错误的。 GCC 的行为完全没有任何意义。 related but not a dupe? 报告了错误67274。 MSVC Community 2015 RC V14.0.22823.1 也将编译所有案例 【参考方案1】:

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

lambda-expressioncompound-statement 产生函数调用运算符的 function-body (8.4), 但出于名称查找 (3.4) 的目的,确定 this (9.3.2) 的类型和值并转换 id-expressions 使用(*this) (9.3.1) 将非静态类成员引用到类成员访问表达式中,compound-statement 被考虑在 lambda-expression 的上下文中. [示例:

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

——结束示例]

由于您在示例中捕获了this,因此名称查找应包括Example 的类成员,因此应找到Example::foo。执行的查找与foo(x) 出现在 lambda-expression 本身的上下文中会发生的情况相同,即如果代码看起来像:

void bar()

    foo(x); // clearly Example::foo(x);

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

【讨论】:

是否有上游错误报告来跟踪这个? @jotik 是的,OP reported it.

以上是关于从通用 lambda 调用 `this` 成员函数 - clang vs gcc的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法使成员函数不能从构造函数调用?

构造函数中调用的代码比 lambda 更简单,该构造函数使用输出参数函数来初始化 const 成员

C++14:以通用 std::function 作为类成员的通用 lambda

如何创建一个可变的通用lambda?

C++ 在 lambda 函数中使用 this 指针和绑定

C++之静态