The C++ concept of a lambda function originates in the lambda calculus and functional programming.

What is a lambda expression in C++?

A lambda is an unnamed function that is useful (in actual programming, not theory) for short snippets of code that are impossible to reuse and are not worth naming.

In C++ a lambda function is defined like this

[]() { } // barebone lambda

or in all its glory

[]() mutable -> T { } // T is the return type, still lacking throw()

[] is the capture list, () the argument list and {} the function body.

“Capturing” variables

So far we’ve not used anything other than what was passed to the lambda within it, but we can also use other variables, within the lambda. If you want to access other variables you can use the capture clause (the [] of the expression), which has so far been unused in these examples, e.g.:

void func1(std::vector<double>& v, const double& epsilon) {
    std::transform(v.begin(), v.end(), v.begin(),
        [epsilon](double d) -> double {
            if (d < epsilon) {
                return 0;
            } else {
                return d;
            }
        });
}

You can capture by both reference and value, which you can specify using & and = respectively:

  • [&epsilon] capture by reference
  • [&] captures all variables used in the lambda by reference
  • [=] captures all variables used in the lambda by value
  • [&, epsilon] captures variables like with [&], but epsilon by value
  • [=, &epsilon] captures variables like with [=], but epsilon by reference

The generated operator() is const by default, with the implication that captures will be const when you access them by default. This has the effect that each call with the same input would produce the same result, however you can mark the lambda as mutable to request that the operator() that is produced is not const.

The argument list

The argument list is the same as in any other C++ function.

void func2(std::vector<int>& v) {
  std::for_each(v.begin(), v.end(), [](int num) {
 /* do something here*/ 
});
}

The function body

The code that will be executed when the lambda is actually called.

void func2(std::vector<int>& v) {
  std::for_each(v.begin(), v.end(), [](int num) {
 std::cout << num + num << std::endl;
});
}

Return type deduction

If a lambda has only one return statement, the return type can be omitted and has the implicit type of decltype(return_statement).

Mutable

If a lambda is marked mutable (e.g. []() mutable { }) it is allowed to mutate the values that have been captured by value.

Use cases

he library defined by the ISO standard benefits heavily from lambdas and raises the usability several bars as now users don’t have to clutter their code with small functors in some accessible scope.

Leave a Reply