Lambda Functions

Contents

Lambda Functions#

reading

A nice lambda cheatsheet is available from hackingcpp.com.

C++ has another type of function called a lambda function. You can think of a lambda as an anonymous function that can capture data directly from its environment and work on it. Lambda functions are typically used when you only need to use a function in a single place.

The general form of a lambda is:

[ capture clause ] ( arguments ) { statements };

with optionally some specifiers between the arguments and statements.

The capture clause tells the compiler how it can access data from the surrounding scope:

  • [=] means it captures objects by value

  • [&] means it captures objects by reference

mixed types of capture are also possible, where you can capture some data by value and others by reference

Note

There can be multiple statements in the {  } part of the lambda function. Each should be terminated with a ;, just like any other C++ we write.

Here’s a simple example:

Listing 94 lambda_examples.cpp#
#include <iostream>

int main() {

    double x{10.0};

    auto f = [=] (double y) {return x + y;};

    std::cout << f(1) << " " << f(2) << " " << f(3) << std::endl;

    auto g = [&] () {x *= 2; return x;};

    std::cout << g() << " " << g() << " " << g() << std::endl;

    std::cout << "x = " << x << std::endl;

}

Here, the function f computes x + y, but only y is an argument of the function. The value (we used [=]) of x is captured from the surrounding scope and used in the function.

In the second example, function g, we captured x by reference [&], so we can update it.

Sort Example#

Lambdas make it easy to provide simple functions as arguments to other functions (like we did with std::ranges::sort() previously). Here’s an implementation of that using a lambda function:

Listing 95 algorithms_functions_lambda.cpp#
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

int main() {

    std::vector<std::string> titles{"a new hope",
                                    "the empire strikes back",
                                    "return of the jedi",
                                    "the phantom menace",
                                    "attack of the clones",
                                    "revenge of the sith",
                                    "the force awakens",
                                    "the last jedi",
                                    "the rise of skywalker"};

    std::ranges::sort(titles);

    for (const auto& e : titles) {
        std::cout << e << std::endl;
    }
    std::cout << std::endl;

    // now sort by string length

    std::ranges::sort(titles,
                      [] (const std::string& a, const std::string& b)
                          {return a.size() < b.size();});

    for (const auto& e : titles) {
        std::cout << e << std::endl;
    }
    std::cout << std::endl;

}

Here, our lambda function is:

[] (const std::string& a, const std::string& b)
   {return a.size() < b.size();}

This means:

  • We don’t capture any data from the surrounding scope, []

  • Our function takes 2 strings as const references, (const std::string& a, const std::string& b)

  • We return a bool by comparing the sizes, {return a.size() < b.size();}

    Note that C++ deduces the return type from the function definition, so we don’t write bool explicitly here.

try it…

We can change the sort to alphabetically by the last letter in the title by doing:

[] (const std::string& a, const std::string& b) {return a.back() < b.back();}