With the following code, I get a compile error C2065 'a': undeclared identifier
(using visual studio 2017):
[] {
auto [a, b] = [] {return std::make_tuple(1, 2); }();
auto r = [&] {return a; }(); //error C2065
}();
However, the following code compiles:
[] {
int a, b;
std::tie(a, b) = [] {return std::make_tuple(1, 2); }();
auto r = [&] {return a; }();
}();
I thought that the two samples were equivalent. Is it a compiler bug or am I missing something ?
A possible workaround is to use a lambda capture with the initializer. The following code compiles fine in Visual Studio 2017 15.5.
Core issue 2313 changed the standard so that structured bindings are never names of variables, making them never capturable.
P0588R1's reformulation of lambda capture wording makes this prohibition explicit:
Note that this wording is supposedly a placeholder while the committee figures out exactly how such captures should work.
Previous answer kept for historical reasons:
This technically should compile, but there's a bug in the standard here.
The standard says that lambdas can only capture variables. And it says that a non-tuple-like structured binding declaration doesn't introduce variables. It introduces names, but those names aren't names of variables.
A tuple-like structured binding declaration, on the other hand, does introduce variables.
a
andb
inauto [a, b] = std::make_tuple(1, 2);
are actual reference-typed variables. So they can be captured by a lambda.Obviously this is not a sane state of affairs, and the committee knows this, so a fix should be forthcoming (though there appears be some disagreement over exactly how capturing a structured binding should work).