cpp/language/lambda

Constructs a : an unnamed function object capable of capturing variables in scope.

Syntax
@1@ Full form.

@2@ Omitted parameter list: function takes no arguments, as if the parameter list were.

@3@ Same as, but specifies a generic lambda and explicitly provides a list of template parameters.

@4@ Same as, but specifies a generic lambda and explicitly provides a list of template parameters.

Explanation
A variable is implicitly defined at the beginning of, with semantics as described.

The lambda expression is a prvalue expression of unique unnamed non-union non-aggregate class type, known as closure type, which is declared (for the purposes of ) in the smallest block scope, class scope, or namespace scope that contains the lambda expression. The closure type has the following members, they cannot be named in a :

{{member|{{small|ClosureType::}}operator({{spar|params}})|2= {{dcl begin}} {{dcl|notes={{mark|static and const may be present, see below}}|1= ret operator(params) { body } }} {{dcl|since=c++14|notes={{mark|generic lambda, static and const may be present, see below}}|1= template ret operator(params) { body } }} {{dcl end}} Executes the body of the lambda-expression, when invoked. When accessing a variable, accesses its captured copy (for the entities captured by copy), or the original object (for the entities captured by reference).

Unless the keyword {{c|mutable}} was used in the lambda specifiers, the cv-qualifier of the function-call operator or operator template is {{c|const}} and the objects that were captured by copy are non-modifiable from inside this {{c|operator}}. Explicit {{c|const}} qualifier is not allowed. The function-call operator or operator template is never virtual and cannot have the {{c|volatile}} qualifier.

{{rrev|since=c++17| The function-call operator or any given operator template specialization is always {{tt|constexpr}} if it satisfies the requirements of a {{rlp|constexpr|constexpr function}}. It is also constexpr if the keyword {{c|constexpr}} was used in the lambda specifiers. }} {{rrev|since=c++20| The function-call operator or any given operator template specialization is an {{rlp|consteval|immediate function}} if the keyword {{c|consteval}} was used in the lambda specifiers. }} {{rrev|since=c++23| The function-call operator or any given operator template specialization is a {{rlp|static#Static member functions|static member function}} if the keyword {{c|static}} was used in the lambda specifiers. }}

{{rrev|since=c++14| For each parameter in {{spar|params}} whose type is specified as {{c|auto}}, an invented template parameter is added to {{spar|template-params}}, in order of appearance. The invented template parameter may be a {{rlp|parameter pack}} if the corresponding function member of {{spar|params}} is a function parameter pack. }}

{{rrev|since=c++20| If the lambda definition uses an explicit template parameter list, that template parameter list is used with {{c|operator}}. For each parameter in {{spar|params}} whose type is specified as {{tt|auto}}, an additional invented template parameter is appended to the end of that template parameter list: }}

The exception specification {{spar|exception}} on the lambda-expression applies to the function-call operator or operator template.

For the purpose of {{rlp|lookup|name lookup}}, determining the type and value of the {{rlp|this|{{tt|this}} pointer}} and for accessing non-static class members, the body of the closure type's function call operator or operator template is considered in the context of the lambda-expression.

{{source|1= struct X { int x, y;   int operator(int); void f {       // the context of the following lambda is the member function X::f [=] -> int {           return operator(this->x + y); // X::operator(this->x + (*this).y)                                            // this has type X*        }; } }; }}

Dangling references
If a non-reference entity is captured by reference, implicitly or explicitly, and the function call operator or a specialization of the function call operator template of the closure object is invoked after the entity's lifetime has ended, undefined behavior occurs. The C++ closures do not extend the lifetimes of objects captured by reference.

Same applies to the lifetime of the current object captured via. }}

Lambda capture
The is a comma-separated list of zero or more captures, optionally beginning with the. The capture list defines the outside variables that are accessible from within the lambda function body. The only capture defaults are
 * (implicitly capture the used automatic variables by reference) and
 * (implicitly capture the used automatic variables by copy).

The current object can be implicitly captured if either capture default is present. If implicitly captured, it is always captured by reference, even if the capture default is.

The syntax of an individual capture in is

@1@ simple by-copy capture @2@ simple by-copy capture that is a @3@ by-copy capture with an @4@ simple by-reference capture @5@ simple by-reference capture that is a @6@ by-reference capture with an initializer @7@ simple by-reference capture of the current object @8@ simple by-copy capture of the current object @9@ by-copy capture with an initializer that is a pack expansion @10@ by-reference capture with an initializer that is a pack expansion

If the capture-default is, subsequent simple captures must not begin with.

If the capture-default is, subsequent simple captures must begin with.

Any capture may appear only once, and its name must be different from any parameter name:

Only lambda-expressions defined at block scope or in a may have a capture-default or captures without initializers. For such lambda-expression, the reaching scope is defined as the set of enclosing scopes up to and including the innermost enclosing function (and its parameters). This includes nested block scopes and the scopes of enclosing lambdas if this lambda is nested.

The in any capture without an initializer (other than the -capture) is looked up using usual  in the reaching scope of the lambda. The result of the lookup must be a with automatic storage duration declared in the reaching scope. The entity is explicitly captured.

If a capture list has a capture-default and does not explicitly capture the enclosing object (as or ), or an automatic variable that is  in the lambda body, it captures it implicitly if
 * the body of the lambda the entity

If the body of a lambda an entity captured by copy, the member of the closure type is accessed. If it is not odr-using the entity, the access is to the original object:

If a lambda odr-uses a reference that is captured by reference, it is using the object referred-to by the original reference, not the captured reference itself:

Within the body of a lambda with capture default, the type of any capturable entity is as if it were captured (and thus const-qualification is often added if the lambda is not ), even though the entity is in an unevaluated operand and not captured (e.g. in ):

Any entity captured by a lambda (implicitly or explicitly) is odr-used by the lambda-expression (therefore, implicit capture by a nested lambda triggers implicit capture in the enclosing lambda).

All implicitly-captured variables must be declared within the reaching scope of the lambda.

If a lambda captures the enclosing object (as or ), either the nearest enclosing function must be a non-static member function or the lambda must be in a :

If a lambda expression ODR-uses  or any variable with automatic storage duration, it must be captured by the lambda expression.

Class members cannot be captured explicitly by a capture without initializer (as mentioned above, only are permitted in the capture list):

When a lambda captures a member using implicit by-copy capture, it does not make a copy of that member variable: the use of a member variable is treated as an expression, and  is always implicitly captured by reference:

Members of members cannot be captured. can only captured by copy.

If a nested lambda captures something that is also captured by the immediately enclosing lambda, then 's capture is transformed as follows:
 * if the enclosing lambda captures by copy,  is capturing the non-static member of 's closure type, not the original variable or ; if  is not mutable, the non-static data member is considered to be const-qualified.
 * if the enclosing lambda captures by reference,  is capturing the original variable or.