Export (0) Print
Expand All

Examples of Lambda Expressions

This article shows how to use lambda expressions in your programs. For an overview of lambda expressions, see Lambda Expressions in C++. For more information about the structure of a lambda expression, see Lambda Expression Syntax.

Because a lambda expression is typed, you can assign it to an auto variable or to a function object, as shown here:

// declaring_lambda_expressions1.cpp
// compile with: /EHsc /W4
#include <functional>
#include <iostream>

int main()
{

    using namespace std;

    // Assign the lambda expression that adds two numbers to an auto variable.
    auto f1 = [](int x, int y) { return x + y; };

    cout << f1(2, 3) << endl;

    // Assign the same lambda expression to a function object.
    function<int(int, int)> f2 = [](int x, int y) { return x + y; };

    cout << f2(3, 4) << endl;
}

For more information, see auto Keyword (Type Deduction), function Class, and Function Call (C++).

Although lambda expressions are most often declared in the body of a method or function, you can declare them anywhere that you can initialize a variable.

The Visual C++ compiler binds a lambda expression to its captured variables when the expression is declared instead of when the expression is called. The following example shows a lambda expression that captures the local variable i by value and the local variable j by reference. Because the lambda expression captures i by value, the reassignment of i later in the program does not affect the result of the expression. However, because the lambda expression captures j by reference, the reassignment of j does affect the result of the expression.

// declaring_lambda_expressions2.cpp
// compile with: /EHsc /W4
#include <functional>
#include <iostream>

int main()
{
   using namespace std;

   int i = 3;
   int j = 5;

   // The following lambda expression captures i by value and
   // j by reference.
   function<int (void)> f = [i, &j] { return i + j; };

   // Change the values of i and j.
   i = 22;
   j = 44;

   // Call f and print its result.
   cout << f() << endl;
}

You can call a lambda expression immediately, as shown in the next code snippet. The second snippet shows how to pass a lambda as an argument to Standard Template Library (STL) algorithms such as find_if.

This example declares a lambda expression that returns the sum of two integers and calls the expression immediately with the arguments 5 and 4:

// calling_lambda_expressions1.cpp
// compile with: /EHsc
#include <iostream>

int main()
{
   using namespace std;
   int n = [] (int x, int y) { return x + y; }(5, 4);
   cout << n << endl;
}

This example passes a lambda expression as an argument to the find_if function. The lambda expression returns true if its parameter is an even number.

// calling_lambda_expressions2.cpp
// compile with: /EHsc /W4
#include <list>
#include <algorithm>
#include <iostream>

int main()
{
    using namespace std;

    // Create a list of integers with a few initial elements.
    list<int> numbers;
    numbers.push_back(13);
    numbers.push_back(17);
    numbers.push_back(42);
    numbers.push_back(46);
    numbers.push_back(99);

    // Use the find_if function and a lambda expression to find the 
    // first even number in the list.
    const list<int>::const_iterator result = 
        find_if(numbers.begin(), numbers.end(),[](int n) { return (n % 2) == 0; });

    // Print the result.
    if (result != numbers.end()) {
        cout << "The first even number in the list is " << *result << "." << endl;
    } else {
        cout << "The list contains no even numbers." << endl;
    }
}

The first even number in the list is 42.

For more information about the find_if function, see find_if. For more information about the STL functions that perform common algorithms, see <algorithm>.

[go to top]

You can nest a lambda expression inside another one, as shown in this example. The inner lambda expression multiplies its argument by 2 and returns the result. The outer lambda expression calls the inner lambda expression with its argument and adds 3 to the result.

// nesting_lambda_expressions.cpp
// compile with: /EHsc /W4
#include <iostream>

int main()
{
    using namespace std;

    // The following lambda expression contains a nested lambda
    // expression.
    int timestwoplusthree = [](int x) { return [](int y) { return y * 2; }(x) + 3; }(5);

    // Print the result.
    cout << timestwoplusthree << endl;
}

In this example, [](int y) { return y * 2; } is the nested lambda expression.

[go to top]

Many programming languages support the concept of a higher-order function. A higher-order function is a lambda expression that takes another lambda expression as its argument or returns a lambda expression. You can use the function class to enable a C++ lambda expression to behave like a higher-order function. The following example shows a lambda expression that returns a function object and a lambda expression that takes a function object as its argument.

// higher_order_lambda_expression.cpp
// compile with: /EHsc /W4
#include <iostream>
#include <functional>

int main()
{
    using namespace std;

    // The following code declares a lambda expression that returns 
    // another lambda expression that adds two numbers. 
    // The returned lambda expression captures parameter x by value.
    auto addtwointegers = [](int x) -> function<int(int)> { 
        return [=](int y) { return x + y; }; 
    };

    // The following code declares a lambda expression that takes another
    // lambda expression as its argument.
    // The lambda expression applies the argument z to the function f
    // and multiplies by 2.
    auto higherorder = [](const function<int(int)>& f, int z) { 
        return f(z) * 2; 
    };

    // Call the lambda expression that is bound to higherorder. 
    auto answer = higherorder(addtwointegers(7), 8);

    // Print the result, which is (7+8)*2.
    cout << answer << endl;
}

You can use lambda expressions in the body of a method. The lambda expression can access any method or data member that the enclosing method can access. You can explicitly or implicitly capture the this pointer to provide access to methods and data members of the enclosing class.

You can use the this pointer explicitly in a method, as shown here:

void ApplyScale(const vector<int>& v) const
{
   for_each(v.begin(), v.end(), 
      [this](int n) { cout << n * _scale << endl; });
}

You can also capture the this pointer implicitly:

void ApplyScale(const vector<int>& v) const
{
   for_each(v.begin(), v.end(), 
      [=](int n) { cout << n * _scale << endl; });
}

The following example shows the Scale class, which encapsulates a scale value.

// method_lambda_expression.cpp
// compile with: /EHsc /W4
#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

class Scale
{
public:
    // The constructor.
    explicit Scale(int scale) : _scale(scale) {}

    // Prints the product of each element in a vector object 
    // and the scale value to the console.
    void ApplyScale(const vector<int>& v) const
    {
        for_each(v.begin(), v.end(), [=](int n) { cout << n * _scale << endl; });
    }

private:
    int _scale;
};

int main()
{
    vector<int> values;
    values.push_back(1);
    values.push_back(2);
    values.push_back(3);
    values.push_back(4);

    // Create a Scale object that scales elements by 3 and apply
    // it to the vector object. Does not modify the vector.
    Scale s(3);
    s.ApplyScale(values);
}

3
6
9
12

The ApplyScale method uses a lambda expression to print the product of the scale value and each element in a vector object. The lambda expression implicitly captures this so that it can access the _scale member.

[go to top]

Because lambda expressions are typed, you can use them with C++ templates. The following example shows the negate_all and print_all functions. The negate_all function applies the unary operator- to each element in the vector object. The print_all function prints each element in the vector object to the console.

// template_lambda_expression.cpp
// compile with: /EHsc
#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

// Negates each element in the vector object. Assumes signed data type.
template <typename T>
void negate_all(vector<T>& v)
{
    for_each(v.begin(), v.end(), [](T& n) { n = -n; });
}

// Prints to the console each element in the vector object.
template <typename T>
void print_all(const vector<T>& v)
{
    for_each(v.begin(), v.end(), [](const T& n) { cout << n << endl; });
}

int main()
{
    // Create a vector of signed integers with a few elements.
    vector<int> v;
    v.push_back(34);
    v.push_back(-43);
    v.push_back(56);

    print_all(v);
    negate_all(v);
    cout << "After negate_all():" << endl;
    print_all(v);
}

34
-43
56
After negate_all():
-34
43
-56

For more information about C++ templates, see Templates.

[go to top]

The body of a lambda expression follows the rules for both structured exception handling (SEH) and C++ exception handling. You can handle a raised exception in the body of a lambda expression or defer exception handling to the enclosing scope. The following example uses the for_each function and a lambda expression to fill a vector object with the values of another one. It uses a try/catch block to handle invalid access to the first vector.

// eh_lambda_expression.cpp
// compile with: /EHsc /W4
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
    // Create a vector that contains 3 elements.
    vector<int> elements(3);

    // Create another vector that contains index values.
    vector<int> indices(3);
    indices[0] = 0;
    indices[1] = -1; // This is not a valid subscript. It will trigger an exception.
    indices[2] = 2;

    // Use the values from the vector of index values to 
    // fill the elements vector. This example uses a 
    // try/catch block to handle invalid access to the 
    // elements vector.
    try
    {
        for_each(indices.begin(), indices.end(), [&](int index) { 
            elements.at(index) = index; 
        });
    }
    catch (const out_of_range& e)
    {
        cerr << "Caught '" << e.what() << "'." << endl;
    };
}

Caught 'invalid vector<T> subscript'.

For more information about exception handling, see Exception Handling in Visual C++.

[go to top]

The capture clause of a lambda expression cannot contain a variable that has a managed type. However, you can pass an argument that has a managed type to the parameter list of a lambda expression. The following example contains a lambda expression that captures the local unmanaged variable ch by value and takes a System.String object as its parameter.

// managed_lambda_expression.cpp
// compile with: /clr
using namespace System;

int main()
{
    char ch = '!'; // a local unmanaged variable

    // The following lambda expression captures local variables
    // by value and takes a managed String object as its parameter.
    [=](String ^s) { 
        Console::WriteLine(s + Convert::ToChar(ch)); 
    }("Hello");
}

You can also use lambda expressions with the STL/CLR library. For more information, see STL/CLR Library Reference.

Important note Important

Lambdas are not supported in these common language runtime (CLR) managed entities: ref class, ref struct, value class, and value struct.

[go to top]

Community Additions

ADD
Show:
© 2014 Microsoft