Structured binding is a C++17 language feature that allows the unpacking of multi-value types—such as arrays, tuples, and aggregate classes—into distinct, named identifiers in a single declaration. It provides a compiler-level mechanism to bind a list of identifiers to the subobjects or elements of an evaluated expression.Documentation Index
Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
Use this file to discover all available pages before exploring further.
Syntax
attr: Optional attributes (e.g.,[[maybe_unused]]).cv-auto: Theautokeyword, optionally modified byconstorvolatile.ref-operator: Optional&(lvalue reference) or&&(forwarding reference).identifier-list: A comma-separated list of names to bind to the elements.expression: The object being unpacked.
Underlying Mechanics
When a structured binding is declared, the compiler does not directly assign the evaluatedexpression to the identifiers. Instead, it generates a hidden, anonymous variable (often conceptually referred to as e) initialized by the expression.
The cv-auto and ref-operator qualifiers apply to this hidden variable, not directly to the identifiers. The identifiers in the identifier-list are then created as aliases to the specific elements or members of e.
Binding Protocols
The compiler resolves the unpacking process by evaluating the type of the hidden variablee against three distinct protocols, evaluated in the following order:
1. Array Binding
Ife is an array type, the identifiers bind to the array elements in increasing index order. The number of identifiers in the list must exactly match the number of elements in the array.
2. Tuple-Like Binding
If the type ofe supports the tuple protocol, the compiler utilizes template metaprogramming hooks to unpack the object. Specifically, the type must have a complete std::tuple_size<E> specialization.
The compiler binds each identifier using std::tuple_element<I, E>::type to determine the type, and extracts the value using a get<I>() function. The compiler resolves get<I>() by first looking for a member function e.get<I>(), and if not found, falls back to Argument-Dependent Lookup (ADL) for a non-member get<I>(e).
3. Data Member Binding
Ife is neither an array nor tuple-like, it must be a class or struct type. The compiler binds the identifiers to the non-static data members of e in declaration order.
For this to be well-formed:
- All non-static data members must be public.
- All non-static data members must be declared in the same class definition (either all in the derived class or all in the same unambiguous base class).
- The class or struct must not contain any anonymous union members.
- The number of identifiers must exactly match the number of non-static data members.
Type Deduction and decltype Behavior
Because the identifiers are aliases rather than standard variables, querying their type via decltype yields the exact declared type of the referenced member or element, modified by the cv-qualifiers of the hidden variable e. However, decltype explicitly does not inherit the reference qualifiers of e.
If e is a const value, the bound identifiers will be treated as const types, even if the original struct members were not declared const, because they are aliasing members of a const object. Conversely, if e is a reference type, decltype on the identifier will not reflect that reference. For example, if e is Point& and Point has a member int x, decltype(px) evaluates to int, not int&.
Master C++ with Deep Grasping Methodology!Learn More





