DEV Community

panmanio
panmanio

Posted on • Edited on • Originally published at burnicki.pl

6 2

Capture structured bindings in C++17

C++17 introduced a handy construct called structured binding:

const auto [first, second] = std::make_tuple(1,2);
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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; }();
Enter fullscreen mode Exit fullscreen mode

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; }();
Enter fullscreen mode Exit fullscreen mode

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:


  1. There is a difference in handling tuple-like structs and other structs. You can check this reference for more details. 

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more