ラムダ式の例Examples of Lambda Expressions

この記事では、プログラムでラムダ式を使用する方法を示します。This article shows how to use lambda expressions in your programs. ラムダ式の概要については、「ラムダ式」を参照してください。For an overview of lambda expressions, see Lambda Expressions. ラムダ式の構造の詳細については、「ラムダ式の構文」を参照してください。For more information about the structure of a lambda expression, see Lambda Expression Syntax.

ラムダ式の宣言Declaring Lambda Expressions

例 1Example 1

auto 次に示すように、ラムダ式は型指定されているため、変数またはオブジェクトに割り当てることができ function ます。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

詳細については、「」 auto 、「 function クラス」、および「関数呼び出し」を参照してください。For more information, see auto, function Class, and Function Call.

ラムダ式は関数の本体で最も頻繁に宣言されますが、変数を初期化できる場所ならどこでも宣言できます。Although lambda expressions are most often declared in the body of a function, you can declare them anywhere that you can initialize a variable.

例 2Example 2

Microsoft C++ コンパイラは、式が呼び出されたときではなく、式が宣言されるときに、そのキャプチャされた変数にラムダ式をバインドします。The Microsoft C++ compiler binds a lambda expression to its captured variables when the expression is declared instead of when the expression is called. 次の例では、ローカル変数 i を明示的に値でキャプチャし、ローカル変数 j を暗黙的に参照でキャプチャするラムダ式を示しています。The following example shows a lambda expression that captures the local variable i by value and the local variable j by reference. ラムダ式は i を値でキャプチャするため、プログラムが後で i を再割り当てしても式の結果に影響しません。Because the lambda expression captures i by value, the reassignment of i later in the program does not affect the result of the expression. ただし、ラムダ式は j を参照でキャプチャするため、j の再割り当ては式の結果に影響します。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

[この記事の中][In This Article]

ラムダ式の呼び出しCalling Lambda Expressions

次のコード スニペットに示しているように、ラムダ式は直接呼び出すことができます。You can call a lambda expression immediately, as shown in the next code snippet. 2番目のスニペットは、ラムダを、などの C++ 標準ライブラリアルゴリズムに引数として渡す方法を示して find_if います。The second snippet shows how to pass a lambda as an argument to C++ Standard Library algorithms such as find_if.

例 1Example 1

この例は、2 つの整数値の合計を返し、引数 54 で直接、式を呼び出すラムダ式を宣言します。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

例 2Example 2

この例は、find_if 関数の引数としてラムダ式を渡します。This example passes a lambda expression as an argument to the find_if function. ラムダ式は、 true そのパラメーターが偶数の場合にを返します。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

関数の詳細については find_if 、「」を参照してください find_ifFor more information about the find_if function, see find_if. 一般的なアルゴリズムを実行する C++ 標準ライブラリ関数の詳細については、「」を参照してください <algorithm>For more information about the C++ Standard Library functions that perform common algorithms, see <algorithm>.

[この記事の中][In This Article]

ラムダ式の入れ子Nesting Lambda Expressions

Example

この例に示しているように、ラムダ式を別のラムダ式の入れ子にすることができます。You can nest a lambda expression inside another one, as shown in this example. 内側のラムダ式は、その引数を 2 倍し、その結果を返します。The inner lambda expression multiplies its argument by 2 and returns the result. 外側のラムダ式は、引数を持つ内側のラムダ式を呼び出し、結果に 3 を追加します。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

この例では、[](int y) { return y * 2; } は入れ子になったラムダ式です。In this example, [](int y) { return y * 2; } is the nested lambda expression.

[この記事の中][In This Article]

高階ラムダ関数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. クラスを使用して、 function C++ ラムダ式が高階関数のように動作できるようにすることができます。You can use the function class to enable a C++ lambda expression to behave like a higher-order function. この例は、function オブジェクトを返すラムダ式と、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

[この記事の中][In This Article]

関数でのラムダ式の使用Using a Lambda Expression in a Function

Example

関数の本体でラムダ式を使用できます。You can use lambda expressions in the body of a function. ラムダ式は、外側の関数がアクセスできる任意の関数またはデータ メンバーにアクセスできます。The lambda expression can access any function or data member that the enclosing function can access. ポインターを明示的または暗黙的にキャプチャして、 this 外側のクラスの関数とデータメンバーにアクセスできるようにすることができます。You can explicitly or implicitly capture the this pointer to provide access to functions and data members of the enclosing class. Visual Studio 2017 バージョン15.3 以降(で使用可能 /std:c++17 ): this 元の [*this] オブジェクトがスコープ外になった後にコードが実行される可能性がある非同期操作または並列操作でラムダを使用する場合は、値によってキャプチャします。Visual Studio 2017 version 15.3 and later (available with /std:c++17): Capture this by value ([*this]) when the lambda will be used in asynchronous or parallel operations where the code might execute after the original object goes out of scope.

this 次に示すように、関数でポインターを明示的に使用することができます。You can use the this pointer explicitly in a function, as shown here:

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

// capture "this" by value (Visual Studio 2017 version 15.3 and later)
void ApplyScale2(const vector<int>& v) const
{
   for_each(v.begin(), v.end(),
      [*this](int n) { cout << n * _scale << endl; });
}

ポインターを暗黙的にキャプチャすることもでき this ます。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; });
}

次の例は、スケール値をカプセル化する Scale クラスを示しています。The following example shows the Scale class, which encapsulates a scale value.

// function_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

ApplyScale 関数は、ラムダ式を使用してスケール値と vector オブジェクト内の各要素の積を出力します。The ApplyScale function uses a lambda expression to print the product of the scale value and each element in a vector object. ラムダ式は、 this メンバーにアクセスできるように暗黙的にキャプチャし _scale ます。The lambda expression implicitly captures this so that it can access the _scale member.

[この記事の中][In This Article]

テンプレートでのラムダ式の使用Using Lambda Expressions with Templates

Example

ラムダ式は型指定されているため、それらを C++ テンプレートで使用できます。Because lambda expressions are typed, you can use them with C++ templates. negate_all 関数および print_all 関数の例を次に示します。The following example shows the negate_all and print_all functions. 関数は、 negate_all オブジェクトの operator- 各要素に単項を適用し vector ます。The negate_all function applies the unary operator- to each element in the vector object. print_all 関数は、vector オブジェクトの各要素をコンソールに出力します。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

C++ テンプレートの詳細については、「テンプレート」を参照してください。For more information about C++ templates, see Templates.

[この記事の中][In This Article]

例外の処理Handling Exceptions

Example

ラムダ式の本体は、構造化例外処理 (SEH: Structured Exception Handling) および C++ 例外処理の規則に従います。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. 次の例では、関数とラムダ式を使用して、 for_each vector 別のオブジェクトの値をオブジェクトに格納します。The following example uses the for_each function and a lambda expression to fill a vector object with the values of another one. ブロックを使用して、 try / catch 最初のベクターへの無効なアクセスを処理します。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 This Article]

マネージ型でのラムダ式の使用 (C++/CLI)Using Lambda Expressions with Managed Types (C++/CLI)

Example

ラムダ式の capture 句には、マネージド型の変数を含めることができません。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. この例に示しているラムダ式は、ローカル非マネージ型変数 ch を値でキャプチャし、System.String オブジェクトをパラメーターとして受け取ります。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.

コード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

ラムダ式を STL/CLR ライブラリで使用することもできます。You can also use lambda expressions with the STL/CLR library. 詳細については、「 STL/CLR ライブラリリファレンス」を参照してください。For more information, see STL/CLR Library Reference.

重要

ラムダは、共通言語ランタイム (CLR) マネージエンティティ ( ref class 、、 ref struct value class 、および) ではサポートされていません value structLambdas are not supported in these common language runtime (CLR) managed entities: ref class, ref struct, value class, and value struct.

[この記事の中][In This Article]

関連項目See also

ラムダ式Lambda Expressions
ラムダ式の構文Lambda Expression Syntax
auto
function講義function Class
find_if
<algorithm>
関数呼び出しFunction Call
テンプレートTemplates
例外処理Exception Handling
STL/CLR ライブラリリファレンスSTL/CLR Library Reference