C++17 introduced a handy construct called structured binding:
const auto [first, second] = std::make_tuple(1,2);
Structured bindings are used to decompose arrays and structs/classes 1 to named subobjects. Almost any object with non-static, accessible data members can be destructured this way. It works even for bit-fields:
struct BF { int x : 2; };
const auto bf (BF{1});
const auto& [y] = bf;
Resulting aliases (first
, second
and y
in the examples above) are actually not mere variables but rather identifiers or aliases.
This may feel unintuitive but there actually is a case when we cannot use these aliases as other variables. According to this C++ Language Standard working draft we cannot use structured bindings in lambda capture list:
If a lambda-expression explicitly captures an entity that is not odr-usable or captures a structured binding (explicitly or implicitly), the program is ill-formed.
(emphasis mine). That means following code is illegal:
auto [a, b, c] = std::make_tuple(1, 3, 7);
auto d = [b] { return b; }();
It actually works on gcc
(10.3) and msvc
(v19.28) but fails on clang
(12.0.0):
error: 'b' in capture list does not name a variable
This restriction does not apply for init-captures, which is reasonable as with init-captures there is a new variable defined that is captured and this variable is no longer the structured binding, so this compiles well in clang
, gcc
and msvc
:
auto [a, b, c] = std::make_tuple(2, 7, 2);
auto d = [&b = b] { return b; }();
The standard got reworded along the way and in C++ 20 final working draft the restriction is no longer there. But clang
still fails, even with -std=c++20
, while gcc
and msvc
are fine with both simple- and init-capture of the structured binding. I feel way more comfortable with gcc
and msvc
way as there is no need to provide special construct only to capture a single value.
Interesting resources:
- C++ Language Standard working draft N4713 (2017-11-27)
- C++20 Language Standard final working draft N4861 (2020-04-01)
- Why structured bindings can't declare variables? a Reddit post
- Lambda implicit capture fails with variable declared from structured binding Stack overflow thread
- Reference capture of structured bindings: a Public Proposal (2019-02-22)
- Changes between C++17 and C++20 DIS "Improvements for structured bindings" listed here (2020-03-02)
- A brief introduction to C++ structured binding by Raymond on devblogs.microsoft.com
-
There is a difference in handling tuple-like structs and other structs. You can check this reference for more details. ↩
Top comments (0)