使用以下代码,我收到编译错误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; }();
}();
我认为这两个样本是等价的。它是编译器错误还是我错过了什么?
答案 0 :(得分:25)
Core issue 2313更改了标准,以便结构化绑定永远不会是变量的名称,从而使它们永远无法被捕获。
P0588R1重新制定lambda捕获措辞使这一禁令明确:
如果lambda表达式[...]捕获结构化绑定(显式 或隐含地),该计划是不正确的。
请注意,这个措辞应该是一个占位符,而委员会确切地知道这些捕获应该如何运作。
以前的答案保留了历史原因:
这在技术上应该编译,但标准中存在一个错误。
标准说lambdas只能捕获变量。并且它说非类似元组的结构化绑定声明不会引入变量。它引入了名称,但这些名称不是变量的名称。
另一方面,类似于元组的结构化绑定声明 引入变量。 a
中的b
和auto [a, b] = std::make_tuple(1, 2);
是实际的
引用类型变量。所以他们可以被lambda捕获。
显然,这不是一个理智的事情,委员会知道这一点,所以应该即将出现一个解决方案(尽管对于如何捕获结构化绑定应该如何工作似乎存在一些分歧。)
答案 1 :(得分:5)
可能的解决方法是使用初始化程序的lambda捕获。以下代码在Visual Studio 2017 15.5中编译良好。
[] {
auto[a, b] = [] {return std::make_tuple(1, 2); }();
auto r = [a = a] {return a; }();
}();