Стандарт C++ 11 (1119564), страница 32
Текст из файла (страница 32)
An entity captured by a lambda-expressionis odr-used (3.2) in the scope containing the lambda-expression. If this is captured by a local lambdaexpression, its nearest enclosing function shall be a non-static member function. If a lambda-expressionodr-uses (3.2) this or a variable with automatic storage duration from its reaching scope, that entity shallbe captured by the lambda-expression. If a lambda-expression captures an entity and that entity is notdefined or captured in the immediately enclosing lambda expression or function, the program is ill-formed.[ Example:void f1(int i) {int const N = 20;auto m1 = [=]{int const M = 30;auto m2 = [i]{int x[N][M];x[0][0] = i;// OK: N and M are not odr-used// OK: i is explicitly captured by m2§ 5.1.294© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)// and implicitly captured by m1};};struct s1 {int f;void work(int n) {int m = n*n;int j = 40;auto m3 = [this,m] {auto m4 = [&,j] {int x = n;x += m;x += i;x += f;////////////////error: j not captured by m3error: n implicitly captured by m4but not captured by m3OK: m implicitly captured by m4and explicitly captured by m3error: i is outside of the reaching scopeOK: this captured implicitly by m4and explicitly by m3};};}};}— end example ]13A lambda-expression appearing in a default argument shall not implicitly or explicitly capture any entity.[ Example:void f2() {int i = 1;void g1(intvoid g2(intvoid g3(intvoid g4(intvoid g5(int}=====([i]{ return i; })());([i]{ return 0; })());([=]{ return i; })());([=]{ return 0; })());([]{ return sizeof i; })());//////////ill-formedill-formedill-formedOKOK— end example ]14An entity is captured by copy if it is implicitly captured and the capture-default is = or if it is explicitlycaptured with a capture that does not include an &.
For each entity captured by copy, an unnamed nonstatic data member is declared in the closure type. The declaration order of these members is unspecified.The type of such a data member is the type of the corresponding captured entity if the entity is not areference to an object, or the referenced type otherwise. [ Note: If the captured entity is a reference to afunction, the corresponding data member is also a reference to a function. — end note ]15An entity is captured by reference if it is implicitly or explicitly captured but not captured by copy.
It isunspecified whether additional unnamed non-static data members are declared in the closure type for entitiescaptured by reference.16If a lambda-expression m2 captures an entity and that entity is captured by an immediately enclosing lambdaexpression m1, then m2’s capture is transformed as follows:— if m1 captures the entity by copy, m2 captures the corresponding non-static data member of m1’s closuretype;— if m1 captures the entity by reference, m2 captures the same entity captured by m1.§ 5.1.2© ISO/IEC 2011 – All rights reserved95ISO/IEC 14882:2011(E)[ Example: the nested lambda expressions and invocations below will output 123234.int a = 1, b = 1, c = 1;auto m1 = [a, &b, &c]() mutable {auto m2 = [a, b, &c]() mutable {std::cout << a << b << c;a = 4; b = 4; c = 4;};a = 3; b = 3; c = 3;m2();};a = 2; b = 2; c = 2;m1();std::cout << a << b << c;— end example ]17Every id-expression that is an odr-use (3.2) of an entity captured by copy is transformed into an access to thecorresponding unnamed data member of the closure type.
[ Note: An id-expression that is not an odr-userefers to the original entity, never to a member of the closure type. Furthermore, such an id-expressiondoes not cause the implicit capture of the entity. — end note ] If this is captured, each odr-use of thisis transformed into an access to the corresponding unnamed data member of the closure type, cast (5.4)to the type of this. [ Note: The cast ensures that the transformed expression is a prvalue. — end note ][ Example:void f(const int*);void g() {const int N = 10;[=] {int arr[N];f(&N);// OK: not an odr-use, refers to automatic variable// OK: causes N to be captured; &N points to the// corresponding member of the closure type}}— end example ]18Every occurrence of decltype((x)) where x is a possibly parenthesized id-expression that names an entityof automatic storage duration is treated as if x were transformed into an access to a corresponding datamember of the closure type that would have been declared if x were an odr-use of the denoted entity.[ Example:void f3() {float x, &r = x;[=] {decltype(x) y1;decltype((x)) y2 = y1;decltype(r) r1 = y1;decltype((r)) r2 = y2;////////////x and r are not captured (appearance in a decltype operand is not an odr-use)y1 has type floaty2 has type float const& because this lambdais not mutable and x is an lvaluer1 has type float& (transformation not considered)r2 has type float const&};}— end example ]19The closure type associated with a lambda-expression has a deleted (8.4.3) default constructor and a deletedcopy assignment operator.
It has an implicitly-declared copy constructor (12.8) and may have an implicitly§ 5.1.296© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)declared move constructor (12.8). [ Note: The copy/move constructor is implicitly defined in the same wayas any other implicitly declared copy/move constructor would be implicitly defined. — end note ]20The closure type associated with a lambda-expression has an implicitly-declared destructor (12.4).21When the lambda-expression is evaluated, the entities that are captured by copy are used to direct-initializeeach corresponding non-static data member of the resulting closure object.
(For array members, the arrayelements are direct-initialized in increasing subscript order.) These initializations are performed in the(unspecified) order in which the non-static data members are declared. [ Note: This ensures that thedestructions will occur in the reverse order of the constructions. — end note ]22[ Note: If an entity is implicitly or explicitly captured by reference, invoking the function call operator ofthe corresponding lambda-expression after the lifetime of the entity has ended is likely to result in undefinedbehavior. — end note ]23A capture followed by an ellipsis is a pack expansion (14.5.3).
[ Example:template<class... Args>void f(Args... args) {auto lm = [&, args...] { return g(args...); };lm();}— end example ]5.21Postfix expressions[expr.post]Postfix expressions group left-to-right.postfix-expression:primary-expressionpostfix-expression [ expression ]postfix-expression [ braced-init-list ]postfix-expression ( expression-listopt )simple-type-specifier ( expression-listopt )typename-specifier ( expression-listopt )simple-type-specifier braced-init-listtypename-specifier braced-init-listpostfix-expression . templateopt id-expressionpostfix-expression -> templateopt id-expressionpostfix-expression .
pseudo-destructor-namepostfix-expression -> pseudo-destructor-namepostfix-expression ++postfix-expression -dynamic_cast < type-id > ( expression )static_cast < type-id > ( expression )reinterpret_cast < type-id > ( expression )const_cast < type-id > ( expression )typeid ( expression )typeid ( type-id )expression-list:initializer-list§ 5.2© ISO/IEC 2011 – All rights reserved97ISO/IEC 14882:2011(E)pseudo-destructor-name:nested-name-specifieropt type-name :: ~ type-namenested-name-specifier template simple-template-id :: ~ type-namenested-name-specifieropt ~ type-name~ decltype-specifier2[ Note: The > token following the type-id in a dynamic_cast, static_cast, reinterpret_cast, or const_cast may be the product of replacing a >> token by two consecutive > tokens (14.2).
— end note ]5.2.1Subscripting[expr.sub]1A postfix expression followed by an expression in square brackets is a postfix expression. One of the expressions shall have the type “pointer to T” and the other shall have unscoped enumeration or integral type.The result is an lvalue of type “T.” The type “T” shall be a completely-defined object type.62 The expressionE1[E2] is identical (by definition) to *((E1)+(E2)) [ Note: see 5.3 and 5.7 for details of * and + and 8.3.4for details of arrays.
— end note ]2A braced-init-list shall not be used with the built-in subscript operator.5.2.2Function call[expr.call]1There are two kinds of function call: ordinary function call and member function63 (9.3) call. A functioncall is a postfix expression followed by parentheses containing a possibly empty, comma-separated list ofexpressions which constitute the arguments to the function. For an ordinary function call, the postfixexpression shall be either an lvalue that refers to a function (in which case the function-to-pointer standardconversion (4.3) is suppressed on the postfix expression), or it shall have pointer to function type. Calling afunction through an expression whose function type has a language linkage that is different from the languagelinkage of the function type of the called function’s definition is undefined (7.5). For a member functioncall, the postfix expression shall be an implicit (9.3.1, 9.4) or explicit class member access (5.2.5) whose idexpression is a function member name, or a pointer-to-member expression (5.5) selecting a function member;the call is as a member of the class object referred to by the object expression.
In the case of an implicitclass member access, the implied object is the one pointed to by this. [ Note: a member function call of theform f() is interpreted as (*this).f() (see 9.3.1). — end note ] If a function or member function nameis used, the name can be overloaded (Clause 13), in which case the appropriate function shall be selectedaccording to the rules in 13.3. If the selected function is non-virtual, or if the id-expression in the classmember access expression is a qualified-id, that function is called. Otherwise, its final overrider (10.3) in thedynamic type of the object expression is called. [ Note: the dynamic type is the type of the object referredto by the current value of the object expression.
12.7 describes the behavior of virtual function calls whenthe object expression refers to an object under construction or destruction. — end note ]2[ Note: If a function or member function name is used, and name lookup (3.4) does not find a declaration ofthat name, the program is ill-formed.
No function is implicitly declared by such a call. — end note ]3If the postfix-expression designates a destructor (12.4), the type of the function call expression is void;otherwise, the type of the function call expression is the return type of the statically chosen function (i.e.,ignoring the virtual keyword), even if the type of the function actually called is different. This type shallbe an object type, a reference type or the type void.4When a function is called, each parameter (8.3.5) shall be initialized (8.5, 12.8, 12.1) with its correspondingargument.