【问题标题】:Capture this in lambda attribute inside a templated class vs not-templated class在模板类与非模板类中的 lambda 属性中捕获此内容
【发布时间】:2015-02-15 22:57:11
【问题描述】:

我已经成功编写了一个像这样的类,在定义为所述类的非静态属性的 lambda 中捕获它:

#include <memory>
#include <iostream>
#include <functional>

struct S
{
  S()
  {
    std::cout << "S::S()[" << this << "]" << std::endl;
  }

  std::string y_{"hi mate"};
  int x_;
  std::function<void(int*)> del_{[this](int *ptr)
  {
    std::cout << "Deleting ptr[" << ptr << "] this[" << this << "] this->y_[" << this->y_ << "]" << std::endl;
  }};
  std::unique_ptr<decltype(x_), decltype(del_)> unique_{&x_, del_};
};

int main()
{
  S s;
}

这编译并且似乎运行得很好。

但是,使用模板类,它不再起作用了:

#include <memory>
#include <iostream>
#include <functional>

template <typename>
struct S
{
  S()
  {
    std::cout << "S::S()[" << this << "]" << std::endl;
  }

  std::string y_{"hi mate"};
  int x_;
  std::function<void(int*)> del_{[this](int *ptr)
  {
    std::cout << "Deleting ptr[" << ptr << "] this[" << this << "] this->y_[" << this->y_ << "]" << std::endl;
  }};
  std::unique_ptr<decltype(x_), decltype(del_)> unique_{&x_, del_};
};

int main()
{
  S<int> s;
}

$> g++ -std=c++1y custom_deleter_template.cpp
~/test custom_deleter_template.cpp:在'struct的实例化中 S::': custom_deleter_template.cpp:9:3: 必需 来自'S::S() [与 = int]' custom_deleter_template.cpp:24:10:
此处需要 custom_deleter_template.cpp:15:35: internal 编译器错误:在 tsubst_copy 中,位于 cp/pt.c:12569
std::function del_{[this](int *ptr) ^ 请提交完整的错误报告,并在适当的情况下提供预处理的源代码。看 获取说明。 预处理源存储到 /tmp/pyro/ccxfNspM.out 文件中,请 将此附加到您的错误报告中。

在提交错误报告之前(我不能这样做,他们阻止了帐户创建),根据标准的规定,它不编译是否正常?

编译器是 g++ (Ubuntu 4.9.2-0ubuntu1~14.04) 4.9.2,使用标志 -std=c++1y。标志 -std=c++11 也会发生同样的情况。

【问题讨论】:

  • 内部编译器错误始终是一个错误。这应该像在clang 中那样编译。
  • 我可以在 OS X 上使用 GCC 4.9.2 重现。
  • 它确实在 clang 中编译 :) .
  • 它还使用更新的 g++5.0 编译,所以它可能是一个已经修复的错误。
  • @dyp :您介意提供一个链接以在 linux 上获取 g++5.0 吗?我检查的唯一镜像只有 4.9.x 版本。

标签: c++ templates c++11 lambda gcc4.9


【解决方案1】:

这确实是GCC的一个bug,已经是being tracked了。

它似乎影响了 4.8 和 4.9。正如 cmets 中所指出的,这个特定示例适用于 4.7 和 5.0。您可以亲自查看here 并使用不同版本的 gcc。

但是,您的代码的这个没有外部依赖的简化版本仍然会在 5.0 中崩溃:

template <typename>
struct S {
  int f{[this](){return 42;}()};
};

int main(){
    return S<int>{}.f; //  should return 42
}

我建议您在使用您的代码之前等待我引用的错误被修复,或者切换到另一个编译器;)。

【讨论】:

  • 您的代码无效,并被 clang 拒绝,因为 Lambda&lt;void(int*)&gt; 是一个空结构,没有任何空间来存储任何内容,包括您传递的 lambda。检查一个有效的程序(只给Lambda一个什么都不做的模板化构造函数)是否以同样的方式失败可能很有用。
  • @hvd:您对代码格式错误的看法是对的,但除此之外,GCC 也应该拒绝它,而不是段错误。这表明前端在模板上下文中处理 lambdas 时仍有一些问题。
  • 当然,但是如果 ice-on-valid 已修复,并且只剩下 ice-on-invalid 问题,那么问题会比仍然存在 ice-on-valid 问题的情况要小。
  • @hvd:很公平,我更新了示例,它仍然触发相同的错误但现在有效。
  • @hvd:有趣。我在 20150306 中遇到错误:melpon.org/wandbox/permlink/aDgR5Sev834bhMHd
猜你喜欢
  • 2020-05-02
  • 1970-01-01
  • 1970-01-01
  • 2010-11-08
  • 1970-01-01
  • 1970-01-01
  • 2011-10-08
  • 2010-12-20
  • 2019-08-07
相关资源
最近更新 更多