Lambda 隐式捕获因结构化绑定声明的变量而失败

新手上路,请多包涵

使用以下代码,我得到一个编译错误 C2065 'a': undeclared identifier (使用Visual Studio 2017):

 [] {
    auto [a, b] = [] {return std::make_tuple(1, 2); }();
    auto r = [&] {return a; }(); //error C2065
}();

但是,以下代码编译:

 [] {
    int a, b;
    std::tie(a, b) = [] {return std::make_tuple(1, 2); }();
    auto r = [&] {return a; }();
}();

我认为这两个样本是等价的。是编译器错误还是我遗漏了什么?

原文由 ThreeStarProgrammer57 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
1 个回答

核心问题 2313 更改了标准,因此结构化绑定永远不是变量的名称,使它们永远无法捕获。

P0588R1 对 lambda 捕获措辞的重新表述明确了这一禁令:

如果 lambda 表达式 […] 捕获结构化绑定(显式或隐式),则该程序格式错误。

请注意,这个措辞应该是一个占位符,而委员会确切地弄清楚了这种捕获应该如何工作。

由于历史原因保留了以前的答案:


这在技术上应该可以编译,但是这里的标准中有一个错误。

标准规定 lambda 只能捕获变量。它说非元组的结构化绑定声明不会引入变量。它引入了名称,但这些名称不是变量的名称。

另一方面,类似元组的结构化绑定声明 确实 引入了变量。 abauto [a, b] = std::make_tuple(1, 2); 是实际的引用类型变量。所以它们可以被 lambda 捕获。

显然,这不是一个理智的状态,委员会知道这一点,因此应该会进行修复(尽管对于捕获结构化绑定应该如何工作似乎存在一些分歧)。

原文由 T.C. 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题