Init
This commit is contained in:
215
cppdraft/dcl/struct/bind.md
Normal file
215
cppdraft/dcl/struct/bind.md
Normal file
@@ -0,0 +1,215 @@
|
||||
[dcl.struct.bind]
|
||||
|
||||
# 9 Declarations [[dcl]](./#dcl)
|
||||
|
||||
## 9.7 Structured binding declarations [dcl.struct.bind]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7580)
|
||||
|
||||
A structured binding declaration introduces the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")*s*v0, v1, v2,â¦,vNâ1 of the[*sb-identifier-list*](dcl.pre#nt:sb-identifier-list "9.1 Preamble [dcl.pre]") as names[.](#1.sentence-1)
|
||||
|
||||
An [*sb-identifier*](dcl.pre#nt:sb-identifier "9.1 Preamble [dcl.pre]") that contains an ellipsis
|
||||
introduces a structured binding pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#1.sentence-2)
|
||||
|
||||
A [*structured binding*](#def:structured_binding "9.7 Structured binding declarations [dcl.struct.bind]") is either
|
||||
an [*sb-identifier*](dcl.pre#nt:sb-identifier "9.1 Preamble [dcl.pre]") that does not contain an ellipsis or
|
||||
an element of a structured binding pack[.](#1.sentence-3)
|
||||
|
||||
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") of
|
||||
an [*sb-identifier*](dcl.pre#nt:sb-identifier "9.1 Preamble [dcl.pre]") appertains to the associated structured bindings[.](#1.sentence-4)
|
||||
|
||||
Let cv denote the [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")*s* in
|
||||
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") and*S* consist of
|
||||
each [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]") of the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") that is constexpr, constinit, or
|
||||
a [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]")[.](#1.sentence-5)
|
||||
|
||||
A cv that includes volatile is deprecated;
|
||||
see [[depr.volatile.type]](depr.volatile.type "D.4 Deprecated volatile types")[.](#1.sentence-6)
|
||||
|
||||
First, a variable with a unique name *e* is introduced[.](#1.sentence-7)
|
||||
|
||||
If the[*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") in the [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]") has array type *cv1* A and no [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]") is present,*e* is defined by
|
||||
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt *S* cv A *e* ;
|
||||
|
||||
and each element is copy-initialized or direct-initialized
|
||||
from the corresponding element of the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") as specified
|
||||
by the form of the [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]")[.](#1.sentence-8)
|
||||
|
||||
Otherwise, *e* is defined as-if by
|
||||
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]")opt *e* [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]") ;
|
||||
|
||||
where
|
||||
the declaration is never interpreted as a function declaration and
|
||||
the parts of the declaration other than the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") are taken
|
||||
from the corresponding structured binding declaration[.](#1.sentence-9)
|
||||
|
||||
The type of the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]")*e* is called E[.](#1.sentence-10)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
E is never a reference type ([[expr.prop]](expr.prop "7.2 Properties of expressions"))[.](#1.sentence-11)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7626)
|
||||
|
||||
The [*structured binding size*](#def:structured_binding_size "9.7 Structured binding declarations [dcl.struct.bind]") of E, as defined below,
|
||||
is the number of structured bindings
|
||||
that need to be introduced by the structured binding declaration[.](#2.sentence-1)
|
||||
|
||||
If there is no structured binding pack,
|
||||
then the number of elements in the [*sb-identifier-list*](dcl.pre#nt:sb-identifier-list "9.1 Preamble [dcl.pre]") shall be equal to the structured binding size of E[.](#2.sentence-2)
|
||||
|
||||
Otherwise, the number of non-pack elements shall be no more than
|
||||
the structured binding size of E;
|
||||
the number of elements of the structured binding pack is
|
||||
the structured binding size of E less
|
||||
the number of non-pack elements in the [*sb-identifier-list*](dcl.pre#nt:sb-identifier-list "9.1 Preamble [dcl.pre]")[.](#2.sentence-3)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7639)
|
||||
|
||||
Let SBi denote
|
||||
the ith structured binding in the structured binding declaration
|
||||
after expanding the structured binding pack, if any[.](#3.sentence-1)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
If there is no structured binding pack,
|
||||
then SBi denotes vi[.](#3.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [1](#example-1)*: struct C { int x, y, z; };
|
||||
|
||||
template<class T>void now_i_know_my() {auto [a, b, c] = C(); // OK, SB0 is a, SB1 is b, and SB2 is cauto [d, ...e] = C(); // OK, SB0 is d, the pack e (v1) contains two structured bindings: SB1 and SB2auto [...f, g] = C(); // OK, the pack f (v0) contains two structured bindings: SB0 and SB1, and SB2 is gauto [h, i, j, ...k] = C(); // OK, the pack k is emptyauto [l, m, n, o, ...p] = C(); // error: structured binding size is too small} â *end example*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7662)
|
||||
|
||||
If a structured binding declaration appears as a [*condition*](stmt.pre#nt:condition "8.1 Preamble [stmt.pre]"),
|
||||
the decision variable ([[stmt.pre]](stmt.pre "8.1 Preamble")) of the condition is *e*[.](#4.sentence-1)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7666)
|
||||
|
||||
If the [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]") refers to
|
||||
one of the names introduced by the structured binding declaration,
|
||||
the program is ill-formed[.](#5.sentence-1)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7671)
|
||||
|
||||
E shall not be an array type of unknown bound[.](#6.sentence-1)
|
||||
|
||||
If E is any other array type with element type T,
|
||||
the structured binding size of E is equal to the
|
||||
number of elements of E[.](#6.sentence-2)
|
||||
|
||||
Each SBi is the name of an
|
||||
lvalue that refers to the element i of the array and whose type
|
||||
is T; the referenced type is T[.](#6.sentence-3)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
The top-level cv-qualifiers of T are cv[.](#6.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [2](#example-2)*: auto f() -> int(&)[2];auto [ x, y ] = f(); // x and y refer to elements in a copy of the array return valueauto& [ xr, yr ] = f(); // xr and yr refer to elements in the array referred to by f's return valueauto g() -> int(&)[4];
|
||||
|
||||
template<size_t N>void h(int (&arr)[N]) {auto [a, ...b, c] = arr; // a names the first element of the array, b is a pack referring to the second and// third elements, and c names the fourth elementauto& [...e] = arr; // e is a pack referring to the four elements of the array}void call_h() { h(g());} â *end example*]
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7703)
|
||||
|
||||
Otherwise, if
|
||||
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") std::tuple_size<E> names a complete class type with a member named value,
|
||||
the expression std::tuple_size<E>::value shall be a well-formed integral constant expression
|
||||
and
|
||||
the structured binding size of E is equal to the value of that
|
||||
expression[.](#7.sentence-1)
|
||||
|
||||
Let i be an index prvalue of type std::size_t corresponding to vi[.](#7.sentence-2)
|
||||
|
||||
If a search for the name get in the scope of E ([[class.member.lookup]](class.member.lookup "6.5.2 Member name lookup"))
|
||||
finds at least one declaration
|
||||
that is a function template whose first template parameter
|
||||
is a constant template parameter,
|
||||
the initializer is*e*.get<i>()[.](#7.sentence-3)
|
||||
|
||||
Otherwise, the initializer is get<i>(*e*),
|
||||
where get undergoes argument-dependent lookup ([[basic.lookup.argdep]](basic.lookup.argdep "6.5.4 Argument-dependent name lookup"))[.](#7.sentence-4)
|
||||
|
||||
In either case, get<i> is interpreted as a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]")[.](#7.sentence-5)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
Ordinary [unqualified lookup](basic.lookup.unqual "6.5.3 Unqualified name lookup [basic.lookup.unqual]") is not performed[.](#7.sentence-6)
|
||||
|
||||
â *end note*]
|
||||
|
||||
In either case, *e* is an lvalue if the type of the entity *e* is an lvalue reference and an xvalue otherwise[.](#7.sentence-7)
|
||||
|
||||
Given the type Ti designated bystd::tuple_element<i, E>::type and
|
||||
the type Ui designated by
|
||||
either Ti& or Ti&&,
|
||||
where Ui is an lvalue reference if
|
||||
the initializer is an lvalue and an rvalue reference otherwise,
|
||||
variables are introduced with unique names ri as follows:
|
||||
|
||||
*S* Ui ri = [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]") ;
|
||||
|
||||
Each SBi is the name of an lvalue of type Ti that refers to the object bound to ri;
|
||||
the referenced type is Ti[.](#7.sentence-9)
|
||||
|
||||
The initialization of *e* and
|
||||
any conversion of *e* considered as a decision variable ([[stmt.pre]](stmt.pre "8.1 Preamble"))
|
||||
is
|
||||
sequenced before the initialization of any ri[.](#7.sentence-10)
|
||||
|
||||
The initialization of each ri is
|
||||
sequenced before the initialization of any rj where i<j[.](#7.sentence-11)
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7749)
|
||||
|
||||
Otherwise,
|
||||
all of E's non-static data members
|
||||
shall be direct members of E or
|
||||
of the same base class of E,
|
||||
well-formed when named as *e*.*name* in the context of the structured binding,E shall not have an anonymous union member, and
|
||||
the structured binding size of E is
|
||||
equal to the number of non-static data members of E[.](#8.sentence-1)
|
||||
|
||||
Designating the non-static data members of E asm0, m1, m2,⦠(in declaration order),
|
||||
each SBi is the
|
||||
name of an lvalue that refers to the member mi of *e* and
|
||||
whose type is
|
||||
that of *e*.mi ([[expr.ref]](expr.ref "7.6.1.5 Class member access"));
|
||||
the referenced type is
|
||||
the declared type of mi if that type is a reference type, or
|
||||
the type of *e*.mi otherwise[.](#8.sentence-2)
|
||||
|
||||
The lvalue is a
|
||||
bit-field if that member is a bit-field[.](#8.sentence-3)
|
||||
|
||||
[*Example [3](#example-3)*: struct S { mutable int x1 : 2; volatile double y1; };
|
||||
S f();const auto [ x, y ] = f();
|
||||
|
||||
The type of the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") x is âintâ,
|
||||
the type of the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") y is âconst volatile doubleâ[.](#8.sentence-4)
|
||||
|
||||
â *end example*]
|
||||
Reference in New Issue
Block a user