从通用 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->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->
仅在通用 lambda 的情况下是必需的?
如果没有将 lambda 传递给 call
,为什么不需要 this->
?
谁不符合标准?
【问题讨论】:
你注意到的不一致表明clang在这里是正确的。 甚至不用看标准,我可以绝对肯定地说 Clang 是对的。即使不符合标准,也还是对的;在那种情况下,标准是错误的。 GCC 的行为完全没有任何意义。 related but not a dupe? 报告了错误67274。 MSVC Community 2015 RC V14.0.22823.1 也将编译所有案例 【参考方案1】:这是一个 gcc 错误。来自 [expr.prim.lambda]:
lambda-expression 的 compound-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->foo(x);
。
【讨论】:
是否有上游错误报告来跟踪这个? @jotik 是的,OP reported it.以上是关于从通用 lambda 调用 `this` 成员函数 - clang vs gcc的主要内容,如果未能解决你的问题,请参考以下文章
构造函数中调用的代码比 lambda 更简单,该构造函数使用输出参数函数来初始化 const 成员