GCC不能捕获'this'指向使用init捕获的模板类型的指针 [英] GCC can't capture 'this' pointer to templated type using init-capture

查看:349
本文介绍了GCC不能捕获'this'指向使用init捕获的模板类型的指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

模板类可以在lambda中捕获自己的这个指针:

A templated class can capture its own this pointer in a lambda:

template <typename T>
class Foo {
  public:
    void foo(void) {}
    auto getCallableFoo(void) {
      return [this]() { this->foo(); };
    }
};

这个和所有其他 Foo 使用以下代码测试:

This and all other Foo examples can be tested using the following code:

int main()
{
  Foo<int> f;
  auto callable = f.getCallableFoo();
  callable();
}

但是,如果使用init捕获, GCC:

However, if instead an init-capture is used, this no longer works with GCC:

    auto getCallableFoo(void) {
      return [ptr = this]() { ptr->foo(); };
    }

错误讯息(来自GCC 5.1):

Error message (from GCC 5.1):

error: ‘Foo<T>::getCallableFoo()::<lambda()>::__ptr’ has incomplete type

Clang 3.7似乎可以无错编译和运行此代码。 (我实际上使用的版本是从3.7之前的版本编译的版本,但我不期望这已经破坏从那时起。)

Clang 3.7 appears to compile and run this code without error. (I'm actually using a version compiled from source from before 3.7 was released, but I don't expect this has broken since then.)

Init捕获表现为像 auto 的赋值,但下面的代码似乎在GCC中没有错误地工作:

Init-capture is supposed to behave like assignment to auto, but the following code appears to work without error in GCC:

// New method in Foo:
auto getPtr(void) {
  return this;
}

// Usage:
auto ptr = f.getPtr();
ptr->foo();

那么为什么 ptr 能够捕获GCC中的吗?这是一个错误吗?

So why isn't the ptr value able to capture this in GCC? Is this a bug?

另一个考虑是,根据CppReference 这个被视为一个单独的语法案例从每个其他捕获列表类型。所以这可能是一个暗示,为什么GCC对待这些情况不同。但是我不清楚我对这个特殊情况做了什么(如果有的话)特殊处理,或者为什么这是一个特殊情况。

One other consideration is that, according to CppReference, this is treated as a separate syntactical case from every other capture-list type. So that may be one hint toward why GCC treats these cases differently. But it is not clear to me what (if any) special handling is done for this special case, or why it's a special case at all.

编辑: 看起来这 有效:

return [ptr = static_cast<decltype(this)>(this)]() { ptr->foo(); };

这对我来说没有意义,因为 decltype (不像 auto )完全它的参数类型,因此 static_cast

This makes no sense to me, because decltype (unlike auto) infers exactly the type of its argument, so the static_cast shouldn't actually be affecting anything.

EDITS 2,3,4:这是一个完整的表达式列表,我试过两个编译器,带有指示哪些编译器接受每个表达式的注释:

EDITS 2,3,4: Here's a complete list of expressions that I've tried with both compilers, with comments indicating which compiler(s) accept each expression:

[this]() { this->foo(); };        // Both: work
[ptr = this]() { ptr->foo(); };   // GCC fails
[ptr = static_cast<decltype(this)>(this)]() { ptr->foo(); };   // Both: works (!!!)
[ptr(this)]() { ptr->foo(); };   // GCC fails
[ptr{this}]() { ptr->foo(); };   // GCC works (!!!!!!!!), Clang doesn't work (infers initializer list)
[ptr = {this}]() { ptr->foo(); };   // Both: fail (infers initializer list)
[ptr = &*this]() { ptr->foo(); };  // Both: work
[ptr = &*(this)]() { ptr->foo(); };  // Both: work

对于 [ptr {this}] ,我的版本Clang(一个预发布3.7)警告说,解释会改变;当前它推断一个初始化列表,但是大概以后的版本会(或者已经)推断 this 按照来自N3922的新的 auto

For [ptr{this}], my version of Clang (a pre-release 3.7) warns that the interpretation will change; currently it infers an initializer list, but presumably later versions will (or already do) infer the type of this in accordance with the new auto rules from N3922.

令我震惊的是,GCC允许 [ptr {this}] ,但不是 ptr(this)] 。我没有这个解释。

It shocks me that GCC permits [ptr{this}] but not [ptr(this)]. I have no explanation for this.

推荐答案

这是一个错误。



这是一个错误。我已针对此问题提交了 GCC错误报告。现在已在固定在GCC的中继

如Revolver_Ocelot所述,& * force g ++ 以执行正确的类型推导。因此,我当前的解决方法(这是一个宏内部使用一些指针表达式,可能)捕获 [ptr =& *(ptr_expr) ]

As noted by Revolver_Ocelot, &* appears to force g++ to perform the correct type-deduction. My current workaround (which is inside a macro taking some pointer expression that might be this) is therefore to capture [ptr = &*(ptr_expr)].

如上所述,GCC的Jason美林已经在海湾合作委员会的主干中修正了这一点。他指出 this 指针需要在lambda捕获中进行特殊处理;具体来说,它被视为不是依赖类型。以前,此特殊处理适用于 [this] ,但不适用于 [ptr = this]

As noted above, GCC's Jason Merrill has fixed this in GCC's trunk. He comments that the this pointer requires special handling in lambda captures; specifically, it is treated as though it were not a dependent type. Previously, this special handling applied to [this] but not to [ptr = this].

这篇关于GCC不能捕获'this'指向使用init捕获的模板类型的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆