【问题标题】:Calling `this` member function from generic lambda - clang vs gcc从通用 lambda 调用 `this` 成员函数 - 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 的行为完全没有任何意义。
  • 报告了错误67274
  • MSVC Community 2015 RC V14.0.22823.1 也将编译所有案例

标签: c++ lambda this language-lawyer c++14


【解决方案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.
猜你喜欢
  • 2020-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-23
  • 1970-01-01
  • 2018-02-08
  • 1970-01-01
  • 2018-03-29
相关资源
最近更新 更多