C++ Lambda隐式捕获失败,已从结构化绑定声明变量

C++ Lambda隐式捕获失败,已从结构化绑定声明变量,c++,lambda,visual-studio-2017,c++17,structured-bindings,C++,Lambda,Visual Studio 2017,C++17,Structured Bindings,使用以下代码,我得到一个编译错误C2065'a':未声明的标识符(使用visual studio 2017): 但是,编译以下代码: [] { int a, b; std::tie(a, b) = [] {return std::make_tuple(1, 2); }(); auto r = [&] {return a; }(); }(); 我认为这两个样本是等效的。这是一个编译器错误还是我遗漏了什么?改变了标准,使结构化绑定永远不是变量的名称,使它们永远无法捕

使用以下代码,我得到一个编译错误
C2065'a':未声明的标识符(使用visual studio 2017):

但是,编译以下代码:

[] {
    int a, b;
    std::tie(a, b) = [] {return std::make_tuple(1, 2); }();
    auto r = [&] {return a; }();
}();
我认为这两个样本是等效的。这是一个编译器错误还是我遗漏了什么?

改变了标准,使结构化绑定永远不是变量的名称,使它们永远无法捕获

lambda capture措辞的重新表述明确了这一禁令:

如果lambda表达式[…]捕获结构化绑定(显式 或者隐式地),程序的格式不正确

请注意,这个措词被认为是一个占位符,而委员会则精确地计算出这样的捕获应该如何工作

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


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

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

另一方面,类似元组的结构化绑定声明会引入变量<在
auto[a,b]=std::make_tuple(1,2)中的code>a
b
是实际的 引用类型变量。所以他们可以被一只羔羊抓住


显然,这不是一个明智的状态,委员会也知道这一点,因此应该马上进行修复(尽管在捕获结构化绑定的具体工作方式上似乎存在一些分歧)。

一个可能的解决方法是使用lambda捕获和初始值设定项。以下代码在Visual Studio 2017 15.5中编译良好

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

可能相关:gcc 8.1.1编译时没有抱怨。clang 6.0.1给出了一个错误。AFAICS,事实上(我也可以证明)这现在在
-std=c++17
模式下的
g++
8中工作,这意味着(A)某些修复被视为缺陷并进行了后端口处理,我找不到任何立即的迹象,或者(B)
g++
可能允许它作为扩展,甚至是无意中。C++20允许捕获结构化绑定(如果按值,则单独复制它们)。@ThreeStarProgrammer57;请注意,此处引入的通过引用捕获它们的限制后来被删除(在进一步分析确定不需要其他更改来正确支持它们之后)。一个友好的提醒,此问题已得到解决。目前,类似元组的结构化绑定引入了具有唯一名称的变量,
a
b
命名这些变量所引用的glvalues。@Passenger此修复程序是在当前编译器中实现的吗?有一篇论文正在编写中,可能会改变这一点,但工作论文尚未发生任何变化,所以没有什么需要更新的了。我的每一句话:WTF对C++20做了什么改变?GCC现在允许您从结构化绑定中捕获变量,而clang则不允许。哪种编译器是正确的?让人大吃一惊
[] {
    auto[a, b] = [] {return std::make_tuple(1, 2); }();
    auto r = [a = a] {return a; }();
}();