7 Expressions [expr]

7.5 Primary expressions [expr.prim]

7.5.1 Literals [expr.prim.literal]

A literal is a primary expression.
The type of a literal is determined based on its form as specified in [lex.literal].
A string-literal is an lvalue, a user-defined-literal has the same value category as the corresponding operator call expression described in [lex.ext], and any other literal is a prvalue.

7.5.2 This [expr.prim.this]

The keyword this names a pointer to the object for which a non-static member function ([class.this]) is invoked or a non-static data member's initializer ([class.mem]) is evaluated.
If a declaration declares a member function or member function template of a class X, the expression this is a prvalue of type “pointer to cv-qualifier-seq X” between the optional cv-qualifier-seq and the end of the function-definition, member-declarator, or declarator.
It shall not appear before the optional cv-qualifier-seq and it shall not appear within the declaration of a static member function (although its type and value category are defined within a static member function as they are within a non-static member function).
[Note 1:
This is because declaration matching does not occur until the complete declarator is known.
— end note]
[Note 2:
In a trailing-return-type, the class being defined is not required to be complete for purposes of class member access.
Class members declared later are not visible.
[Example 1: struct A { char g(); template<class T> auto f(T t) -> decltype(t + g()) { return t + g(); } }; template auto A::f(int t) -> decltype(t + g()); — end example]
— end note]
Otherwise, if a member-declarator declares a non-static data member of a class X, the expression this is a prvalue of type “pointer to X” within the optional default member initializer.
It shall not appear elsewhere in the member-declarator.
The expression this shall not appear in any other context.
[Example 2: class Outer { int a[sizeof(*this)]; // error: not inside a member function unsigned int sz = sizeof(*this); // OK: in default member initializer void f() { int b[sizeof(*this)]; // OK struct Inner { int c[sizeof(*this)]; // error: not inside a member function of Inner }; } }; — end example]

7.5.3 Parentheses [expr.prim.paren]

A parenthesized expression (E) is a primary expression whose type, result, and value category are identical to those of E.
The parenthesized expression can be used in exactly the same contexts as those where E can be used, and with the same meaning, except as otherwise indicated.

7.5.4 Names [expr.prim.id]

7.5.4.1 General [expr.prim.id.general]

An id-expression is a restricted form of a primary-expression.
[Note 1: — end note]
An id-expression that denotes a non-static data member or non-static member function of a class can only be used:
  • as part of a class member access in which the object expression refers to the member's class61 or a class derived from that class, or
  • to form a pointer to member ([expr.unary.op]), or
  • if that id-expression denotes a non-static data member and it appears in an unevaluated operand.
    [Example 1: struct S { int m; }; int i = sizeof(S::m); // OK int j = sizeof(S::m + 42); // OK — end example]
A potentially-evaluated id-expression that denotes an immediate function shall appear only
For an id-expression that denotes an overload set, overload resolution is performed to select a unique function ([over.match], [over.over]).
[Note 2:
A program cannot refer to a function with a trailing requires-clause whose constraint-expression is not satisfied, because such functions are never selected by overload resolution.
[Example 2: template<typename T> struct A { static void f(int) requires false; } void g() { A<int>::f(0); // error: cannot call f void (*p1)(int) = A<int>::f; // error: cannot take the address of f decltype(A<int>::f)* p2 = nullptr; // error: the type decltype(A<int>​::​f) is invalid }
In each case, the constraints of f are not satisfied.
In the declaration of p2, those constraints are required to be satisfied even though f is an unevaluated operand.
— end example]
— end note]
This also applies when the object expression is an implicit (*this) ([class.mfct.non-static]).
 

7.5.4.2 Unqualified names [expr.prim.id.unqual]

An identifier is only an id-expression if it has been suitably declared ([dcl.dcl]) or if it appears as part of a declarator-id ([dcl.decl]).
An identifier that names a coroutine parameter refers to the copy of the parameter ([dcl.fct.def.coroutine]).
[Note 1:
A type-name or decltype-specifier prefixed by ~ denotes the destructor of the type so named; see [expr.prim.id.dtor].
Within the definition of a non-static member function, an identifier that names a non-static member is transformed to a class member access expression ([class.mfct.non-static]).
— end note]
The result is the entity denoted by the identifier.
If the entity is a local entity and naming it from outside of an unevaluated operand within the declarative region where the unqualified-id appears would result in some intervening lambda-expression capturing it by copy ([expr.prim.lambda.capture]), the type of the expression is the type of a class member access expression ([expr.ref]) naming the non-static data member that would be declared for such a capture in the closure object of the innermost such intervening lambda-expression.
[Note 2:
If that lambda-expression is not declared mutable, the type of such an identifier will typically be const qualified.
— end note]
Otherwise, the type of the expression is the type of the result.
[Note 3:
If the entity is a template parameter object for a template parameter of type T ([temp.param]), the type of the expression is const T.
— end note]
[Note 4:
The type will be adjusted as described in [expr.type] if it is cv-qualified or is a reference type.
— end note]
The expression is an lvalue if the entity is a function, variable, structured binding, data member, or template parameter object and a prvalue otherwise ([basic.lval]); it is a bit-field if the identifier designates a bit-field.
[Example 1: void f() { float x, &r = x; [=] { decltype(x) y1; // y1 has type float decltype((x)) y2 = y1; // y2 has type float const& because this lambda // is not mutable and x is an lvalue decltype(r) r1 = y1; // r1 has type float& decltype((r)) r2 = y2; // r2 has type float const& }; } — end example]

7.5.4.3 Qualified names [expr.prim.id.qual]

The type denoted by a decltype-specifier in a nested-name-specifier shall be a class or enumeration type.
A nested-name-specifier that denotes a class, optionally followed by the keyword template ([temp.names]), and then followed by the name of a member of either that class ([class.mem]) or one of its base classes, is a qualified-id; [class.qual] describes name lookup for class members that appear in qualified-ids.
The result is the member.
The type of the result is the type of the member.
The result is an lvalue if the member is a static member function or a data member and a prvalue otherwise.
[Note 1:
A class member can be referred to using a qualified-id at any point in its potential scope ([basic.scope.class]).
— end note]
Where type-name ​::​~ type-name is used, the two type-names shall refer to the same type (ignoring cv-qualifications); this notation denotes the destructor of the type so named ([expr.prim.id.dtor]).
The unqualified-id in a qualified-id shall not be of the form ~decltype-specifier.
The nested-name-specifier ​::​ names the global namespace.
A nested-name-specifier that names a namespace ([basic.namespace]), optionally followed by the keyword template ([temp.names]), and then followed by the name of a member of that namespace (or the name of a member of a namespace made visible by a using-directive), is a qualified-id; [namespace.qual] describes name lookup for namespace members that appear in qualified-ids.
The result is the member.
The type of the result is the type of the member.
The result is an lvalue if the member is a function, a variable, or a structured binding ([dcl.struct.bind]) and a prvalue otherwise.
A nested-name-specifier that denotes an enumeration, followed by the name of an enumerator of that enumeration, is a qualified-id that refers to the enumerator.
The result is the enumerator.
The type of the result is the type of the enumeration.
The result is a prvalue.
In a qualified-id, if the unqualified-id is a conversion-function-id, its conversion-type-id is first looked up in the class denoted by the nested-name-specifier of the qualified-id and the name, if found, is used.
Otherwise, it is looked up in the context in which the entire qualified-id occurs.
In each of these lookups, only names that denote types or templates whose specializations are types are considered.

7.5.4.4 Destruction [expr.prim.id.dtor]

An id-expression that denotes the destructor of a type T names the destructor of T if T is a class type ([class.dtor]), otherwise the id-expression is said to name a pseudo-destructor.
If the id-expression names a pseudo-destructor, T shall be a scalar type and the id-expression shall appear as the right operand of a class member access ([expr.ref]) that forms the postfix-expression of a function call ([expr.call]).
[Note 1:
Such a call ends the lifetime of the object ([expr.call], [basic.life]).
— end note]
[Example 1: struct C { }; void f() { C * pc = new C; using C2 = C; pc->C::~C2(); // OK, destroys *pc C().C::~C(); // undefined behavior: temporary of type C destroyed twice using T = int; 0 .T::~T(); // OK, no effect 0.T::~T(); // error: 0.T is a user-defined-floating-point-literal ([lex.ext]) } — end example]

7.5.5 Lambda expressions [expr.prim.lambda]

7.5.5.1 General [expr.prim.lambda.general]

A lambda-expression provides a concise way to create a simple function object.
[Example 1: #include <algorithm> #include <cmath> void abssort(float* x, unsigned N) { std::sort(x, x + N, [](float a, float b) { return std::abs(a) < std::abs(b); }); } — end example]
A lambda-expression is a prvalue whose result object is called the closure object.
[Note 1:
A closure object behaves like a function object.
— end note]
In the decl-specifier-seq of the lambda-declarator, each decl-specifier shall be one of mutable, constexpr, or consteval.
[Note 2:
The trailing requires-clause is described in [dcl.decl].
— end note]
If a lambda-expression does not include a lambda-declarator, it is as if the lambda-declarator were ().
The lambda return type is auto, which is replaced by the type specified by the trailing-return-type if provided and/or deduced from return statements as described in [dcl.spec.auto].
[Example 2: auto x1 = [](int i){ return i; }; // OK: return type is int auto x2 = []{ return { 1, 2 }; }; // error: deducing return type from braced-init-list int j; auto x3 = []()->auto&& { return j; }; // OK: return type is int& — end example]
A lambda is a generic lambda if the lambda-expression has any generic parameter type placeholders ([dcl.spec.auto]), or if the lambda has a template-parameter-list.
[Example 3: int i = [](int i, auto a) { return i; }(3, 4); // OK: a generic lambda int j = []<class T>(T t, int i) { return i; }(3, 4); // OK: a generic lambda — end example]

7.5.5.2 Closure types [expr.prim.lambda.closure]

The type of a lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type, called the closure type, whose properties are described below.
The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression.
[Note 1:
This determines the set of namespaces and classes associated with the closure type ([basic.lookup.argdep]).
The parameter types of a lambda-declarator do not affect these associated namespaces and classes.
— end note]
The closure type is not an aggregate type.
An implementation may define the closure type differently from what is described below provided this does not alter the observable behavior of the program other than by changing:
An implementation shall not add members of rvalue reference type to the closure type.
The closure type for a lambda-expression has a public inline function call operator (for a non-generic lambda) or function call operator template (for a generic lambda) ([over.call]) whose parameters and return type are described by the lambda-expression's parameter-declaration-clause and trailing-return-type respectively, and whose template-parameter-list consists of the specified template-parameter-list, if any.
The requires-clause of the function call operator template is the requires-clause immediately following < template-parameter-list >, if any.
The trailing requires-clause of the function call operator or operator template is the requires-clause of the lambda-declarator, if any.
[Note 2:
The function call operator template for a generic lambda might be an abbreviated function template ([dcl.fct]).
— end note]
[Example 1: auto glambda = [](auto a, auto&& b) { return a < b; }; bool b = glambda(3, 3.14); // OK auto vglambda = [](auto printer) { return [=](auto&& ... ts) { // OK: ts is a function parameter pack printer(std::forward<decltype(ts)>(ts)...); return [=]() { printer(ts ...); }; }; }; auto p = vglambda( [](auto v1, auto v2, auto v3) { std::cout << v1 << v2 << v3; } ); auto q = p(1, 'a', 3.14); // OK: outputs 1a3.14 q(); // OK: outputs 1a3.14 — end example]
The function call operator or operator template is declared const ([class.mfct.non-static]) if and only if the lambda-expression's parameter-declaration-clause is not followed by mutable.
It is neither virtual nor declared volatile.
Any noexcept-specifier specified on a lambda-expression applies to the corresponding function call operator or operator template.
An attribute-specifier-seq in a lambda-declarator appertains to the type of the corresponding function call operator or operator template.
The function call operator or any given operator template specialization is a constexpr function if either the corresponding lambda-expression's parameter-declaration-clause is followed by constexpr or consteval, or it satisfies the requirements for a constexpr function ([dcl.constexpr]).
It is an immediate function ([dcl.constexpr]) if the corresponding lambda-expression's parameter-declaration-clause is followed by consteval.
[Note 3:
Names referenced in the lambda-declarator are looked up in the context in which the lambda-expression appears.
— end note]
[Example 2: auto ID = [](auto a) { return a; }; static_assert(ID(3) == 3); // OK struct NonLiteral { NonLiteral(int n) : n(n) { } int n; }; static_assert(ID(NonLiteral{3}).n == 3); // error — end example]
[Example 3: auto monoid = [](auto v) { return [=] { return v; }; }; auto add = [](auto m1) constexpr { auto ret = m1(); return [=](auto m2) mutable { auto m1val = m1(); auto plus = [=](auto m2val) mutable constexpr { return m1val += m2val; }; ret = plus(m2()); return monoid(ret); }; }; constexpr auto zero = monoid(0); constexpr auto one = monoid(1); static_assert(add(one)(zero)() == one()); // OK // Since two below is not declared constexpr, an evaluation of its constexpr member function call operator // cannot perform an lvalue-to-rvalue conversion on one of its subobjects (that represents its capture) // in a constant expression. auto two = monoid(2); assert(two() == 2); // OK, not a constant expression. static_assert(add(one)(one)() == two()); // error: two() is not a constant expression static_assert(add(one)(one)() == monoid(2)()); // OK — end example]
[Note 4:
The function call operator or operator template can be constrained ([temp.constr.decl]) by a type-constraint ([temp.param]), a requires-clause ([temp.pre]), or a trailing requires-clause ([dcl.decl]).
[Example 4: template <typename T> concept C1 = /* ... */; template <std::size_t N> concept C2 = /* ... */; template <typename A, typename B> concept C3 = /* ... */; auto f = []<typename T1, C1 T2> requires C2<sizeof(T1) + sizeof(T2)> (T1 a1, T1 b1, T2 a2, auto a3, auto a4) requires C3<decltype(a4), T2> { // T2 is constrained by a type-constraint. // T1 and T2 are constrained by a requires-clause, and // T2 and the type of a4 are constrained by a trailing requires-clause. }; — end example]
— end note]
The closure type for a non-generic lambda-expression with no lambda-capture whose constraints (if any) are satisfied has a conversion function to pointer to function with C++ language linkage having the same parameter and return types as the closure type's function call operator.
The conversion is to “pointer to noexcept function” if the function call operator has a non-throwing exception specification.
The value returned by this conversion function is the address of a function F that, when invoked, has the same effect as invoking the closure type's function call operator on a default-constructed instance of the closure type.
F is a constexpr function if the function call operator is a constexpr function and is an immediate function if the function call operator is an immediate function.
For a generic lambda with no lambda-capture, the closure type has a conversion function template to pointer to function.
The conversion function template has the same invented template parameter list, and the pointer to function has the same parameter types, as the function call operator template.
The return type of the pointer to function shall behave as if it were a decltype-specifier denoting the return type of the corresponding function call operator template specialization.
[Note 5:
If the generic lambda has no trailing-return-type or the trailing-return-type contains a placeholder type, return type deduction of the corresponding function call operator template specialization has to be done.
The corresponding specialization is that instantiation of the function call operator template with the same template arguments as those deduced for the conversion function template.
Consider the following: auto glambda = [](auto a) { return a; }; int (*fp)(int) = glambda;
The behavior of the conversion function of glambda above is like that of the following conversion function: struct Closure { template<class T> auto operator()(T t) const { /* ... */ } template<class T> static auto lambda_call_operator_invoker(T a) { // forwards execution to operator()(a) and therefore has // the same return type deduced /* ... */ } template<class T> using fptr_t = decltype(lambda_call_operator_invoker(declval<T>())) (*)(T); template<class T> operator fptr_t<T>() const { return &lambda_call_operator_invoker; } };
— end note]
[Example 5: void f1(int (*)(int)) { } void f2(char (*)(int)) { } void g(int (*)(int)) { } // #1 void g(char (*)(char)) { } // #2 void h(int (*)(int)) { } // #3 void h(char (*)(int)) { } // #4 auto glambda = [](auto a) { return a; }; f1(glambda); // OK f2(glambda); // error: ID is not convertible g(glambda); // error: ambiguous h(glambda); // OK: calls #3 since it is convertible from ID int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; }; // OK — end example]
The value returned by any given specialization of this conversion function template is the address of a function F that, when invoked, has the same effect as invoking the generic lambda's corresponding function call operator template specialization on a default-constructed instance of the closure type.
F is a constexpr function if the corresponding specialization is a constexpr function and F is an immediate function if the function call operator template specialization is an immediate function.
[Note 6:
This will result in the implicit instantiation of the generic lambda's body.
The instantiated generic lambda's return type and parameter types are required to match the return type and parameter types of the pointer to function.
— end note]
[Example 6: auto GL = [](auto a) { std::cout << a; return a; }; int (*GL_int)(int) = GL; // OK: through conversion function template GL_int(3); // OK: same as GL(3) — end example]
The conversion function or conversion function template is public, constexpr, non-virtual, non-explicit, const, and has a non-throwing exception specification.
[Example 7: auto Fwd = [](int (*fp)(int), auto a) { return fp(a); }; auto C = [](auto a) { return a; }; static_assert(Fwd(C,3) == 3); // OK // No specialization of the function call operator template can be constexpr (due to the local static). auto NC = [](auto a) { static int s; return a; }; static_assert(Fwd(NC,3) == 3); // error — end example]
The lambda-expression's compound-statement yields the function-body ([dcl.fct.def]) of the function call operator, but for purposes of name lookup, determining the type and value of this and transforming id-expressions referring to non-static class members into class member access expressions using (*this) ([class.mfct.non-static]), the compound-statement is considered in the context of the lambda-expression.
[Example 8: struct S1 { int x, y; int operator()(int); void f() { [=]()->int { return operator()(this->x + y); // equivalent to S1​::​operator()(this->x + (*this).y) // this has type S1* }; } }; — end example]
Further, a variable __func__ is implicitly defined at the beginning of the compound-statement of the lambda-expression, with semantics as described in [dcl.fct.def.general].
The closure type associated with a lambda-expression has no default constructor if the lambda-expression has a lambda-capture and a defaulted default constructor otherwise.
It has a defaulted copy constructor and a defaulted move constructor ([class.copy.ctor]).
It has a deleted copy assignment operator if the lambda-expression has a lambda-capture and defaulted copy and move assignment operators otherwise ([class.copy.assign]).
[Note 7:
These special member functions are implicitly defined as usual, and might therefore be defined as deleted.
— end note]
The closure type associated with a lambda-expression has an implicitly-declared destructor ([class.dtor]).
A member of a closure type shall not be explicitly instantiated, explicitly specialized, or named in a friend declaration.

7.5.5.3 Captures [expr.prim.lambda.capture]

simple-capture:
identifier ...
& identifier ...
this
* this
The body of a lambda-expression may refer to local entities of enclosing block scopes by capturing those entities, as described below.
If a lambda-capture includes a capture-default that is &, no identifier in a simple-capture of that lambda-capture shall be preceded by &.
If a lambda-capture includes a capture-default that is =, each simple-capture of that lambda-capture shall be of the form “& identifier ...”, “this”, or “* this.
[Note 1:
The form [&,this] is redundant but accepted for compatibility with ISO C++ 2014.
— end note]
Ignoring appearances in initializers of init-captures, an identifier or this shall not appear more than once in a lambda-capture.
[Example 1: struct S2 { void f(int i); }; void S2::f(int i) { [&, i]{ }; // OK [&, this, i]{ }; // OK, equivalent to [&, i] [&, &i]{ }; // error: i preceded by & when & is the default [=, *this]{ }; // OK [=, this]{ }; // OK, equivalent to [=] [i, i]{ }; // error: i repeated [this, *this]{ }; // error: this appears twice } — end example]
A lambda-expression shall not have a capture-default or simple-capture in its lambda-introducer unless its innermost enclosing scope is a block scope ([basic.scope.block]) or it appears within a default member initializer and its innermost enclosing scope is the corresponding class scope ([basic.scope.class]).
The identifier in a simple-capture is looked up using the usual rules for unqualified name lookup; each such lookup shall find a local entity.
The simple-captures this and * this denote the local entity *this.
An entity that is designated by a simple-capture is said to be explicitly captured.
If an identifier in a simple-capture appears as the declarator-id of a parameter of the lambda-declarator's parameter-declaration-clause, the program is ill-formed.
[Example 2: void f() { int x = 0; auto g = [x](int x) { return 0; }; // error: parameter and simple-capture have the same name } — end example]
An init-capture without ellipsis behaves as if it declares and explicitly captures a variable of the form “auto init-capture ;” whose declarative region is the lambda-expression's compound-statement, except that:
  • if the capture is by copy (see below), the non-static data member declared for the capture and the variable are treated as two different ways of referring to the same object, which has the lifetime of the non-static data member, and no additional copy and destruction is performed, and
  • if the capture is by reference, the variable's lifetime ends when the closure object's lifetime ends.
[Note 2:
This enables an init-capture like “x = std​::​move(x)”; the second “x” must bind to a declaration in the surrounding context.
— end note]
[Example 3: int x = 4; auto y = [&r = x, x = x+1]()->int { r += 2; return x+2; }(); // Updates ​::​x to 6, and initializes y to 7. auto z = [a = 42](int a) { return 1; }; // error: parameter and local variable have the same name — end example]
For the purposes of lambda capture, an expression potentially references local entities as follows:
If an expression potentially references a local entity within a declarative region in which it is odr-usable, and the expression would be potentially evaluated if the effect of any enclosing typeid expressions ([expr.typeid]) were ignored, the entity is said to be implicitly captured by each intervening lambda-expression with an associated capture-default that does not explicitly capture it.
The implicit capture of *this is deprecated when the capture-default is =; see [depr.capture.this].
[Example 4: void f(int, const int (&)[2] = {}); // #1 void f(const int&, const int (&)[1]); // #2 void test() { const int x = 17; auto g = [](auto a) { f(x); // OK: calls #1, does not capture x }; auto g1 = [=](auto a) { f(x); // OK: calls #1, captures x }; auto g2 = [=](auto a) { int selector[sizeof(a) == 1 ? 1 : 2]{}; f(x, selector); // OK: captures x, might call #1 or #2 }; auto g3 = [=](auto a) { typeid(a + x); // captures x regardless of whether a + x is an unevaluated operand }; }
Within g1, an implementation might optimize away the capture of x as it is not odr-used.
— end example]
[Note 4:
The set of captured entities is determined syntactically, and entities might be implicitly captured even if the expression denoting a local entity is within a discarded statement ([stmt.if]).
[Example 5: template<bool B> void f(int n) { [=](auto a) { if constexpr (B && sizeof(a) > 4) { (void)n; // captures n regardless of the value of B and sizeof(int) } }(0); } — end example]
— end note]
An entity is captured if it is captured explicitly or implicitly.
An entity captured by a lambda-expression is odr-used ([basic.def.odr]) in the scope containing the lambda-expression.
[Note 5:
As a consequence, if a lambda-expression explicitly captures an entity that is not odr-usable, the program is ill-formed ([basic.def.odr]).
— end note]
[Example 6: void f1(int i) { int const N = 20; auto m1 = [=]{ int const M = 30; auto m2 = [i]{ int x[N][M]; // OK: N and M are not odr-used x[0][0] = i; // OK: i is explicitly captured by m2 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] { // error: j not odr-usable due to intervening lambda m3 int x = n; // error: n is odr-used but not odr-usable due to intervening lambda m3 x += m; // OK: m implicitly captured by m4 and explicitly captured by m3 x += i; // error: i is odr-used but not odr-usable // due to intervening function and class scopes x += f; // OK: this captured implicitly by m4 and explicitly by m3 }; }; } }; } struct s2 { double ohseven = .007; auto f() { return [this] { return [*this] { return ohseven; // OK }; }(); } auto g() { return [] { return [*this] { }; // error: *this not captured by outer lambda-expression }(); } }; — end example]
[Note 6:
Because local entities are not odr-usable within a default argument ([basic.def.odr]), a lambda-expression appearing in a default argument cannot implicitly or explicitly capture any local entity.
Such a lambda-expression can still have an init-capture if any full-expression in its initializer satisfies the constraints of an expression appearing in a default argument ([dcl.fct.default]).
— end note]
[Example 7: void f2() { int i = 1; void g1(int = ([i]{ return i; })()); // error void g2(int = ([i]{ return 0; })()); // error void g3(int = ([=]{ return i; })()); // error void g4(int = ([=]{ return 0; })()); // OK void g5(int = ([]{ return sizeof i; })()); // OK void g6(int = ([x=1]{ return x; })()); // OK void g7(int = ([x=i]{ return x; })()); // error } — end example]
An entity is captured by copy if
For each entity captured by copy, an unnamed non-static 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 referenced type if the entity is a reference to an object, an lvalue reference to the referenced function type if the entity is a reference to a function, or the type of the corresponding captured entity otherwise.
A member of an anonymous union shall not be captured by copy.
Every id-expression within the compound-statement of a lambda-expression that is an odr-use of an entity captured by copy is transformed into an access to the corresponding unnamed data member of the closure type.
[Note 7:
An id-expression that is not an odr-use refers to the original entity, never to a member of the closure type.
However, such an id-expression can still cause the implicit capture of the entity.
— end note]
If *this is captured by copy, each expression that odr-uses *this is transformed to instead refer to the corresponding unnamed data member of the closure type.
[Example 8: void f(const int*); void g() { const int N = 10; [=] { int arr[N]; // OK: not an odr-use, refers to automatic variable f(&N); // OK: causes N to be captured; &N points to // the corresponding member of the closure type }; } — end example]
An entity is captured by reference if it is implicitly or explicitly captured but not captured by copy.
It is unspecified whether additional unnamed non-static data members are declared in the closure type for entities captured by reference.
If declared, such non-static data members shall be of literal type.
[Example 9: // The inner closure type must be a literal type regardless of how reference captures are represented. static_assert([](int n) { return [&n] { return ++n; }(); }(3) == 4); — end example]
A bit-field or a member of an anonymous union shall not be captured by reference.
An id-expression within the compound-statement of a lambda-expression that is an odr-use of a reference captured by reference refers to the entity to which the captured reference is bound and not to the captured reference.
[Note 8:
The validity of such captures is determined by the lifetime of the object to which the reference refers, not by the lifetime of the reference itself.
— end note]
[Example 10: auto h(int &r) { return [&] { ++r; // Valid after h returns if the lifetime of the // object to which r is bound has not ended }; } — end example]
If a lambda-expression m2 captures an entity and that entity is captured by an immediately enclosing lambda-expression 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 closure type;
  • if m1 captures the entity by reference, m2 captures the same entity captured by m1.
[Example 11:
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]
When the lambda-expression is evaluated, the entities that are captured by copy are used to direct-initialize each corresponding non-static data member of the resulting closure object, and the non-static data members corresponding to the init-captures are initialized as indicated by the corresponding initializer (which may be copy- or direct-initialization).
(For array members, the array elements 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 9:
This ensures that the destructions will occur in the reverse order of the constructions.
— end note]
[Note 10:
If a non-reference entity is implicitly or explicitly captured by reference, invoking the function call operator of the corresponding lambda-expression after the lifetime of the entity has ended is likely to result in undefined behavior.
— end note]
A simple-capture containing an ellipsis is a pack expansion ([temp.variadic]).
An init-capture containing an ellipsis is a pack expansion that introduces an init-capture pack ([temp.variadic]) whose declarative region is the lambda-expression's compound-statement.
[Example 12: template<class... Args> void f(Args... args) { auto lm = [&, args...] { return g(args...); }; lm(); auto lm2 = [...xs=std::move(args)] { return g(xs...); }; lm2(); } — end example]

7.5.6 Fold expressions [expr.prim.fold]

A fold expression performs a fold of a pack ([temp.variadic]) over a binary operator.
fold-operator: one of
+   -   *   /   %   ^   &   |   <<   >>
+=  -=  *=  /=  %=  ^=  &=  |=  <<=  >>=  =
==  !=  <   >   <=  >=  &&  ||  ,   .*   ->*
An expression of the form (... op e) where op is a fold-operator is called a unary left fold.
An expression of the form (e op ...) where op is a fold-operator is called a unary right fold.
Unary left folds and unary right folds are collectively called unary folds.
In a unary fold, the cast-expression shall contain an unexpanded pack ([temp.variadic]).
An expression of the form (e1 op1 ... op2 e2) where op1 and op2 are fold-operators is called a binary fold.
In a binary fold, op1 and op2 shall be the same fold-operator, and either e1 shall contain an unexpanded pack or e2 shall contain an unexpanded pack, but not both.
If e2 contains an unexpanded pack, the expression is called a binary left fold.
If e1 contains an unexpanded pack, the expression is called a binary right fold.
[Example 1: template<typename ...Args> bool f(Args ...args) { return (true && ... && args); // OK } template<typename ...Args> bool f(Args ...args) { return (args + ... + args); // error: both operands contain unexpanded packs } — end example]

7.5.7 Requires expressions [expr.prim.req]

7.5.7.1 General [expr.prim.req.general]

A requires-expression is a prvalue of type bool whose value is described below.
Expressions appearing within a requirement-body are unevaluated operands.
[Example 1:
A common use of requires-expressions is to define requirements in concepts such as the one below: template<typename T> concept R = requires (T i) { typename T::type; {*i} -> std::convertible_­to<const typename T::type&>; };
A requires-expression can also be used in a requires-clause ([temp.pre]) as a way of writing ad hoc constraints on template arguments such as the one below: template<typename T> requires requires (T x) { x + x; } T add(T a, T b) { return a + b; }
The first requires introduces the requires-clause, and the second introduces the requires-expression.
— end example]
A requires-expression may introduce local parameters using a parameter-declaration-clause ([dcl.fct]).
A local parameter of a requires-expression shall not have a default argument.
Each name introduced by a local parameter is in scope from the point of its declaration until the closing brace of the requirement-body.
These parameters have no linkage, storage, or lifetime; they are only used as notation for the purpose of defining requirements.
The parameter-declaration-clause of a requirement-parameter-list shall not terminate with an ellipsis.
[Example 2: template<typename T> concept C = requires(T t, ...) { // error: terminates with an ellipsis t; }; — end example]
The requirement-body contains a sequence of requirements.
These requirements may refer to local parameters, template parameters, and any other declarations visible from the enclosing context.
The substitution of template arguments into a requires-expression may result in the formation of invalid types or expressions in its requirements or the violation of the semantic constraints of those requirements.
In such cases, the requires-expression evaluates to false; it does not cause the program to be ill-formed.
The substitution and semantic constraint checking proceeds in lexical order and stops when a condition that determines the result of the requires-expression is encountered.
If substitution (if any) and semantic constraint checking succeed, the requires-expression evaluates to true.
[Note 1:
If a requires-expression contains invalid types or expressions in its requirements, and it does not appear within the declaration of a templated entity, then the program is ill-formed.
— end note]
If the substitution of template arguments into a requirement would always result in a substitution failure, the program is ill-formed; no diagnostic required.
[Example 3: template<typename T> concept C = requires { new int[-(int)sizeof(T)]; // ill-formed, no diagnostic required }; — end example]

7.5.7.2 Simple requirements [expr.prim.req.simple]

A simple-requirement asserts the validity of an expression.
[Note 1:
The enclosing requires-expression will evaluate to false if substitution of template arguments into the expression fails.
— end note]
[Example 1: template<typename T> concept C = requires (T a, T b) { a + b; // C<T> is true if a + b is a valid expression }; — end example]
A requirement that starts with a requires token is never interpreted as a simple-requirement.
[Note 2:
This simplifies distinguishing between a simple-requirement and a nested-requirement.
— end note]

7.5.7.3 Type requirements [expr.prim.req.type]

A type-requirement asserts the validity of a type.
[Note 1:
The enclosing requires-expression will evaluate to false if substitution of template arguments fails.
— end note]
[Example 1: template<typename T, typename T::type = 0> struct S; template<typename T> using Ref = T&; template<typename T> concept C = requires { typename T::inner; // required nested member name typename S<T>; // required class template specialization typename Ref<T>; // required alias template substitution, fails if T is void }; — end example]
A type-requirement that names a class template specialization does not require that type to be complete ([basic.types]).

7.5.7.4 Compound requirements [expr.prim.req.compound]

A compound-requirement asserts properties of the expression E.
Substitution of template arguments (if any) and verification of semantic properties proceed in the following order:
  • Substitution of template arguments (if any) into the expression is performed.
  • If the noexcept specifier is present, E shall not be a potentially-throwing expression ([except.spec]).
  • If the return-type-requirement is present, then:
    • Substitution of template arguments (if any) into the return-type-requirement is performed.
    • The immediately-declared constraint ([temp.param]) of the type-constraint for decltype((E)) shall be satisfied.
      [Example 1:
      Given concepts C and D, requires { { E1 } -> C; { E2 } -> D<A, , A>; }; is equivalent to requires { E1; requires C<decltype((E1))>; E2; requires D<decltype((E2)), A, , A>; }; (including in the case where n is zero).
      — end example]
[Example 2: template<typename T> concept C1 = requires(T x) { {x++}; };
The compound-requirement in C1 requires that x++ is a valid expression.
It is equivalent to the simple-requirement x++;.
template<typename T> concept C2 = requires(T x) { {*x} -> std::same_­as<typename T::inner>; };
The compound-requirement in C2 requires that *x is a valid expression, that typename T​::​inner is a valid type, and that std​::​same_­as<decltype((*x)), typename T​::​inner> is satisfied.
template<typename T> concept C3 = requires(T x) { {g(x)} noexcept; };
The compound-requirement in C3 requires that g(x) is a valid expression and that g(x) is non-throwing.
— end example]

7.5.7.5 Nested requirements [expr.prim.req.nested]

A nested-requirement can be used to specify additional constraints in terms of local parameters.
The constraint-expression shall be satisfied ([temp.constr.decl]) by the substituted template arguments, if any.
Substitution of template arguments into a nested-requirement does not result in substitution into the constraint-expression other than as specified in [temp.constr.constr].
[Example 1:
template<typename U> concept C = sizeof(U) == 1; template<typename T> concept D = requires (T t) { requires C<decltype (+t)>; }; D<T> is satisfied if sizeof(decltype (+t)) == 1 ([temp.constr.atomic]).
— end example]
A local parameter shall only appear as an unevaluated operand within the constraint-expression.
[Example 2: template<typename T> concept C = requires (T a) { requires sizeof(a) == 4; // OK requires a == 0; // error: evaluation of a constraint variable }; — end example]