Структурированная связывании декларация вводит identifiers v0, v1, v2, ... из identifier-listкак названия ([basic.scope.declarative]), называется structured bindingс. Позвольте cv обозначить cv-qualifiers в decl-specifier-seq. Сначала вводится переменная с уникальным именем e . Если assignment-expressionв initializer имеет тип массива, A а не ref-qualifierприсутствует, e имеет тип, cv A и каждый элемент инициализируется копией или инициализируется напрямую из соответствующего элемента, assignment-expressionкак указано в форме initializer. В противном случае e определяется как если бы
attribute-specifier-seqopt decl-specifier-seq ref-qualifieropt e initializer ;
где объявление никогда не интерпретируется как объявление функции, а части объявления, кроме declarator-id, взяты из соответствующего объявления структурированной привязки. Тип id-expression e называется E. [ Note: E никогда не является ссылочным типом (пункт [expr]). ] — end note
Если E это тип массива с типом элемента T, количество элементов в identifier-listдолжно быть равно количеству элементов E. Каждый vi - это имя lvalue, которое относится к элементу i массива и имеет тип T; ссылочный тип - T. [ Note: CV-квалификаторы верхнего уровня T are cv. ] [ — end note Example:
auto f() -> int(&)[2]; auto [ x, y ] = f(); // x and y refer to elements in a copy of the array return value auto& [ xr, yr ] = f(); // xr and yr refer to elements in the array referred to by f's return value
— end example ]
В противном случае, если qualified-id std::tuple_size<E> имена являются полным типом, выражение std::tuple_size<E>::value должно быть правильно сформированным интегральным константным выражением, а количество элементов в identifier-listэлементе должно быть равно значению этого выражения. unqualified-id get Ищется в объеме E путем class member access lookup, и если , который находит по крайней мере , одна декларация, то инициализатор e.get<i>(). В противном случае инициализатор находится там get<i>(e), где get ищется в associated namespaces. В любом случае get<i> интерпретируется как template-id. [ Note: Обычный unqualified lookup не выполняется. ] В любом случае является lvalue, если тип объекта является ссылкой lvalue, и xvalue в противном случае. Принимая во внимание типа обозначен , каждый представляет собой переменную типа «ссылка на » инициализируется инициализатор, где ссылка является ссылкой , если именующим инициализатор является Левым и ссылкой на Rvalue в противном случае; ссылочный тип - . — end note e e Ti std::tuple_element<i, E>::type vi Ti Ti
В противном случае все Eнестатические элементы данных должны быть общедоступными прямыми членами одного E и того же однозначного общедоступного базового класса E, E не должны иметь анонимного члена объединения, а количество элементов в классе identifier-listдолжно быть равно количеству нестатических элементов. -статические данные членов E. Обозначая нестатические элементы данных , E как m0, m1, m2, ... (в порядке декларации), каждый vi является именем именующего , который относится к элементу mi из e и типа которого является cv Ti, где Ti находится объявленный тип этого члена; ссылочный тип - cv Ti. Lvalue является битовым полем, если этот член является битовым полем. [ Example:
struct S { int x1 : 2; volatile double y1; }; S f(); const auto [ x, y ] = f();
Тип id-expression x - «const int», тип id-expression y - «const volatile double». ] — end example