Structured binding declaration (since C++17)

Binds the specified names to subobjects or elements of the initializer.

# Notes

Structured bindings cannot be constrained:

The lookup for member get ignores accessibility as usual and also ignores the exact type of the non-type template parameter. A private template<char*> void get(); member will cause the member interpretation to be used, even though it is ill-formed.

The portion of the declaration preceding [ applies to the hidden variable e, not to the introduced structured bindings:

The tuple-like interpretation is always used if std::tuple_size is a complete type with a member named value, even if that would cause the program to be ill-formed:

The usual rules for reference-binding to temporaries (including lifetime-extension) apply if a ref-qualifier is present and the expression is a prvalue. In those cases the hidden variable e is a reference that binds to the temporary variable materialized from the prvalue expression, extending its lifetime. As usual, the binding will fail if e is a non-const lvalue reference:

decltype(x), where x denotes a structured binding, names the referenced type of that structured binding. In the tuple-like case, this is the type returned by std::tuple_element, which may not be a reference even though a hidden reference is always introduced in this case. This effectively emulates the behavior of binding to a struct whose non-static data members have the types returned by std::tuple_element, with the referenceness of the binding itself being a mere implementation detail.

Structured bindings cannot be captured by lambda expressions:

A structured binding size is allowed to be 0 as long as the sb-identifier-list contains exactly one identifier that can only introduce an empty structured binding pack.

# Example

#include <iomanip>
#include <iostream>
#include <set>
#include <string>
 
int main()
{
    std::set<std::string> myset{"hello"};
 
    for (int i{2}; i; --i)
    {
        if (auto [iter, success] = myset.insert("Hello"); success) 
            std::cout << "Insert is successful. The value is "
                      << std::quoted(*iter) << ".\n";
        else
            std::cout << "The value " << std::quoted(*iter)
                      << " already exists in the set.\n";
    }
 
    struct BitFields
    {
        // C++20: default member initializer for bit-fields
        int b : 4 {1}, d : 4 {2}, p : 4 {3}, q : 4 {4};
    };
 
    {
        const auto [b, d, p, q] = BitFields{};
        std::cout << b << ' ' << d << ' ' << p << ' ' << q << '\n';
    }
 
    {
        const auto [b, d, p, q] = []{ return BitFields{4, 3, 2, 1}; }();
        std::cout << b << ' ' << d << ' ' << p << ' ' << q << '\n';
    }
 
    {
        BitFields s;
 
        auto& [b, d, p, q] = s;
        std::cout << b << ' ' << d << ' ' << p << ' ' << q << '\n';
 
        b = 4, d = 3, p = 2, q = 1;
        std::cout << s.b << ' ' << s.d << ' ' << s.p << ' ' << s.q << '\n';
    }
}

# Defect reports

DRApplied toBehavior as publishedCorrect behavior
CWG 2285C++17expression could refer to the names from identifier-listthe declaration isill-formed in this case
CWG 2312C++17the meaning of mutable was lost in case 3its meaning is still kept
CWG 2313C++17in case 2, the structure binding variables could be redeclaredcannot be redeclared
CWG 2339C++17in case 2, the definition of I was missingadded the definition
CWG 2341(P1091R3)C++17structured bindings could not bedeclared with static storage durationallowed
CWG 2386C++17the “tuple-like” binding protocol was usedwhenever std::tuple_size is a complete typeused only when std::tuple_sizehas a member value
CWG 2506C++17if expression is of a cv-qualified array type,the cv-qualification was carried over to Ediscards that cv-qualification
CWG 2635C++20structured bindings could be constrainedprohibited
CWG 2867C++17the initialization order was unclearmade clear
P0961R1C++17in case 2, member get was usedif lookup finds a get of any kindonly if lookup finds a functiontemplate with a non-type parameter
P0969R0C++17in case 3, the members were required to be publiconly required to be accessiblein the context of the declaration

# See also