Condividi tramite


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.

In This Article

Declaring Lambda Expressions

Calling Lambda Expressions

Nesting Lambda Expressions

Higher-Order Lambda Functions

Using a Lambda Expression in a Method

Using Lambda Expressions with Templates

Handling Exceptions

Using Lambda Expressions with Managed Types

Declaring Lambda Expressions

Example 1

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

Code

// 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;
}

Output

5
7

Remarks

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.

Example 2

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.

Code

// 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;
}

Output

47

[go to top]

Calling Lambda Expressions

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.

Example 1

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

Code

// 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;
}

Output

9

Example 2

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.

Code

// 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;
    }
}

Output

The first even number in the list is 42.

Remarks

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]

Nesting Lambda Expressions

Example

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.

Code

// 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;
}

Output

13

Remarks

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

[go to top]

Higher-Order Lambda Functions

Example

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.

Code

// 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;
}

Output

30

[go to top]

Using a Lambda Expression in a Method

Example

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);
}

Output

3
6
9
12

Remarks

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]

Using Lambda Expressions with Templates

Example

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.

Code

// 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);
}

Output

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

Remarks

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

[go to top]

Handling Exceptions

Example

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.

Code

// 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;
    };
}

Output

Caught 'invalid vector<T> subscript'.

Remarks

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

[go to top]

Using Lambda Expressions with Managed Types

Example

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 String object as its parameter.

Code

// 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");
}

Output

Hello!

Remarks

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

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]

See Also

Reference

Lambda Expressions in C++

Lambda Expression Syntax

auto Keyword (Type Deduction)

function Class

find_if

<algorithm>

Function Call (C++)

Exception Handling in Visual C++

Other Resources

Templates

STL/CLR Library Reference