Wyrażenia lambda w języku C++Lambda Expressions in C++

W języku C++ 11 i nowszych wyrażenia lambda — często nazywane wyrażeniem lambda— jest wygodnym sposobem definiowania anonimowego obiektu funkcji ( zamykania) w miejscu, w którym jest wywoływana lub przenoszona jako argument do funkcji.In C++11 and later, a lambda expression—often called a lambda—is a convenient way of defining an anonymous function object (a closure) right at the location where it is invoked or passed as an argument to a function. Zazwyczaj wyrażenia lambda są używane do hermetyzacji kilku wierszy kodu, które są przesyłane do algorytmów lub metod asynchronicznych.Typically lambdas are used to encapsulate a few lines of code that are passed to algorithms or asynchronous methods. W tym artykule zdefiniowano, czym są lambdy, porównano je z innymi technikami programowania, omówiono ich zalety i dostarczono podstawowe przykłady.This article defines what lambdas are, compares them to other programming techniques, describes their advantages, and provides a basic example.

Części wyrażenia lambdaParts of a Lambda Expression

Standard ISO C++ pokazuje proste wyrażenie lambda, które jest przesyłane jako trzeci argument do std::sort() funkcji:The ISO C++ Standard shows a simple lambda that is passed as the third argument to the std::sort() function:

#include <algorithm>
#include <cmath>

void abssort(float* x, unsigned n) {
    std::sort(x, x + n,
        // Lambda expression begins
        [](float a, float b) {
            return (std::abs(a) < std::abs(b));
        } // end of lambda expression
    );
}

Na tej ilustracji przedstawiono części wyrażenia lambda:This illustration shows the parts of a lambda:

Elementy strukturalne wyrażenia lambdaStructural elements of a lambda expression

  1. klauzula Capture (znana również jako wprowadzenie wyrażenia lambda w specyfikacji języka C++)capture clause (Also known as the lambda-introducer in the C++ specification.)

  2. Lista parametrów Obowiązkowe.parameter list Optional. (Znany również jako deklarator lambda)(Also known as the lambda declarator)

  3. Specyfikacja modyfikowalna Obowiązkowe.mutable specification Optional.

  4. Specyfikacja wyjątku Obowiązkowe.exception-specification Optional.

  5. końcowe — typ zwracany Obowiązkowe.trailing-return-type Optional.

  6. treść lambda.lambda body.

Klauzula przechwytywaniaCapture Clause

Wyrażenie lambda może wprowadzać nowe zmienne w swojej treści (w języku C++ 14) i może również uzyskać dostęp do zmiennych lub przechwycić je z zakresu otaczającego.A lambda can introduce new variables in its body (in C++14), and it can also access, or capture, variables from the surrounding scope. Lambda zaczyna się od klauzuli przechwytywania (wyrażenie lambda w standardowej składni), która określa zmienne, które są przechwytywane oraz czy przechwytywanie jest przez wartość, czy przez odwołanie.A lambda begins with the capture clause (lambda-introducer in the Standard syntax), which specifies which variables are captured, and whether the capture is by value or by reference. Zmienne, które mają prefiks handlowego "i" ( & ) są dostępne przez odwołanie i zmienne, które nie są dostępne przez wartość.Variables that have the ampersand (&) prefix are accessed by reference and variables that do not have it are accessed by value.

Pusta Klauzula przechwytywania, [ ] , wskazuje, że treść wyrażenia lambda nie uzyskuje dostępu do żadnych zmiennych w zakresie otaczającym.An empty capture clause, [ ], indicates that the body of the lambda expression accesses no variables in the enclosing scope.

Można użyć domyślnego trybu przechwytywania (wartość Domyślna przechwytywania w standardowej składni), aby wskazać, jak przechwycić wszystkie zmienne zewnętrzne, do których odwołuje się wyrażenie lambda: [&] oznacza, że wszystkie zmienne, do których odwołuje się, są przechwytywane przez odwołanie i oznacza, że [=] są przechwytywane przez wartość.You can use the default capture mode (capture-default in the Standard syntax) to indicate how to capture any outside variables that are referenced in the lambda: [&] means all variables that you refer to are captured by reference, and [=] means they are captured by value. Można użyć domyślnego trybu przechwytywania, a następnie jawnie określić tryb odwrotny dla określonych zmiennych.You can use a default capture mode, and then specify the opposite mode explicitly for specific variables. Na przykład jeśli treść wyrażenia lambda uzyskuje dostęp do zewnętrznej zmiennej total przez odwołanie i zewnętrzną zmienną factor według wartości, następujące klauzule przechwytywania są równoważne:For example, if a lambda body accesses the external variable total by reference and the external variable factor by value, then the following capture clauses are equivalent:

[&total, factor]
[factor, &total]
[&, factor]
[factor, &]
[=, &total]
[&total, =]

Podczas używania przechwytywania domyślnego są przechwytywane tylko zmienne, które są wymienione w wyrażeniach lambda.Only variables that are mentioned in the lambda are captured when a capture-default is used.

Jeśli klauzula przechwytywania zawiera funkcję przechwytywania domyślnego & , a następnie nie ma identifier jej w capture klauzuli przechwytywania, może mieć postać & identifier .If a capture clause includes a capture-default &, then no identifier in a capture of that capture clause can have the form & identifier. Podobnie, Jeśli klauzula Capture zawiera funkcję przechwytywania domyślnego = , a następnie żadna capture z tych klauzuli przechwytywania nie może mieć formularza = identifier .Likewise, if the capture clause includes a capture-default =, then no capture of that capture clause can have the form = identifier. Identyfikator lub this nie może występować więcej niż raz w klauzuli Capture.An identifier or this cannot appear more than once in a capture clause. Poniższy fragment kodu ilustruje kilka przykładów.The following code snippet illustrates some examples.

struct S { void f(int i); };

void S::f(int i) {
    [&, i]{};      // OK
    [&, &i]{};     // ERROR: i preceded by & when & is the default
    [=, this]{};   // ERROR: this when = is the default
    [=, *this]{ }; // OK: captures this by value. See below.
    [i, i]{};      // ERROR: i repeated
}

Przechwytywanie, po którym następuje wielokropek, jest rozwinięciem pakietu, jak pokazano w tym przykładzie szablonu wariadyczne :A capture followed by an ellipsis is a pack expansion, as shown in this variadic template example:

template<class... Args>
void f(Args... args) {
    auto x = [args...] { return g(args...); };
    x();
}

Aby użyć wyrażeń lambda w treści metody klasy, Przekaż this wskaźnik do klauzuli przechwytywania, aby zapewnić dostęp do metod i składowych danych otaczającej klasy.To use lambda expressions in the body of a class method, pass the this pointer to the capture clause to provide access to the methods and data members of the enclosing class.

Visual Studio 2017 w wersji 15,3 lub nowszej (dostępny w /std: c++ 17): this wskaźnik może być przechwytywany przez wartość przez określenie *this w klauzuli Capture.Visual Studio 2017 version 15.3 and later (available with /std:c++17): The this pointer may be captured by value by specifying *this in the capture clause. Przechwyć według wartości oznacza, że całe Zamknięcie, które jest obiektem funkcji anonimowej, który encapulates wyrażenie lambda, jest kopiowane do każdej lokacji wywołań, w której jest wywoływana lambda.Capture by value means that the entire closure, which is the anonymous function object that encapulates the lambda expression, is copied to every call site where the lambda is invoked. Przechwytywanie według wartości jest przydatne, gdy lambda będzie wykonywana w operacjach równoległych lub asynchronicznych, szczególnie w przypadku niektórych architektur sprzętowych, takich jak NUMA.Capture by value is useful when the lambda will execute in parallel or asynchronous operations, especially on certain hardware architectures such as NUMA.

Aby zapoznać się z przykładem, który pokazuje, jak używać wyrażeń lambda z metodami klasy, zobacz "przykład: Używanie wyrażenia lambda w metodzie" w przykładach wyrażeń lambda.For an example that shows how to use lambda expressions with class methods, see "Example: Using a Lambda Expression in a Method" in Examples of Lambda Expressions.

W przypadku korzystania z klauzuli Capture zaleca się pozostawienie tych punktów, szczególnie w przypadku używania wyrażeń lambda z wielowątkowością:When you use the capture clause, we recommend that you keep these points in mind, particularly when you use lambdas with multithreading:

  • Przechwytywania odwołań można użyć do modyfikacji zmiennych poza, ale przechwytywanie wartości nie może.Reference captures can be used to modify variables outside, but value captures cannot. ( mutable umożliwia modyfikowanie kopii, ale nie ich oryginałów).(mutable allows copies to be modified, but not originals.)

  • Przechwytywanie odwołań odzwierciedla aktualizacje zmiennych poza, ale przechwycenia wartości nie.Reference captures reflect updates to variables outside, but value captures do not.

  • Przechwytywanie odwołań wprowadza zależność okresu istnienia, ale przechwycenia wartości nie ma zależności okresu istnienia.Reference captures introduce a lifetime dependency, but value captures have no lifetime dependencies. Jest to szczególnie ważne, gdy lambda przebiega asynchronicznie.This is especially important when the lambda runs asynchronously. W przypadku przechwycenia elementu lokalnego przez odwołanie w asynchronicznym wyrażeniu lambda, ten lokalny będzie bardzo prawdopodobnie wypadał przez czas, gdy zostanie uruchomione wyrażenie lambda, co spowodowało naruszenie zasad dostępu w czasie wykonywania.If you capture a local by reference in an async lambda, that local will very possibly be gone by the time the lambda runs, resulting in an access violation at run time.

Przechwytywanie uogólnione (C++ 14)Generalized capture (C++ 14)

W języku C++ 14 można wprowadzać i inicjować nowe zmienne w klauzuli Capture bez konieczności, aby te zmienne istniały w zakresie otaczającym funkcję lambda.In C++14, you can introduce and initialize new variables in the capture clause, without the need to have those variables exist in the lambda function’s enclosing scope. Inicjowanie można wyrazić jako dowolne dowolne wyrażenie; Typ nowej zmiennej jest wywnioskowany na podstawie typu utworzonego przez wyrażenie.The initialization can be expressed as any arbitrary expression; the type of the new variable is deduced from the type produced by the expression. Jedną z zalet tej funkcji jest to, że w języku C++ 14 można przechwytywać zmienne tylko do przenoszenia (takie jak std:: unique_ptr) z otaczającego zakresu i używać ich w wyrażeniach lambda.One benefit of this feature is that in C++14 you can capture move-only variables (such as std::unique_ptr) from the surrounding scope and use them in a lambda.

pNums = make_unique<vector<int>>(nums);
//...
      auto a = [ptr = move(pNums)]()
        {
           // use ptr
        };

Lista parametrówParameter List

Oprócz zmiennych przechwytywania wyrażenie lambda może akceptować parametry wejściowe.In addition to capturing variables, a lambda can accept input parameters. Lista parametrów (lambda deklarator w standardowej składni) jest opcjonalna i w większości aspektów przypomina listę parametrów dla funkcji.A parameter list (lambda declarator in the Standard syntax) is optional and in most aspects resembles the parameter list for a function.

auto y = [] (int first, int second)
{
    return first + second;
};

W języku C++ 14, jeśli typem parametru jest ogólne, można użyć auto słowa kluczowego jako specyfikatora typu.In C++14, if the parameter type is generic, you can use the auto keyword as the type specifier. Nakazuje kompilatorowi utworzenie operatora wywołania funkcji jako szablonu.This tells the compiler to create the function call operator as a template. Każde wystąpienie elementu auto na liście parametrów jest równoważne parametrowi typu DISTINCT.Each instance of auto in a parameter list is equivalent to a distinct type parameter.

auto y = [] (auto first, auto second)
{
    return first + second;
};

Wyrażenie lambda może przyjmować inne wyrażenie lambda jako argument.A lambda expression can take another lambda expression as its argument. Aby uzyskać więcej informacji, zobacz "wyrażenia lambda wyższego rzędu" w temacie Przykłady wyrażeń lambda.For more information, see "Higher-Order Lambda Expressions" in the topic Examples of Lambda Expressions.

Ponieważ lista parametrów jest opcjonalna, można pominąć puste nawiasy, jeśli nie przechodzą argumentów do wyrażenia lambda, a jego lambda-deklarator nie zawiera specyfikacji wyjątku, końcowego-return-Type lub mutable .Because a parameter list is optional, you can omit the empty parentheses if you do not pass arguments to the lambda expression and its lambda-declarator does not contain exception-specification, trailing-return-type, or mutable.

Specyfikacja modyfikowalnaMutable Specification

Zazwyczaj operator wywołania funkcji lambda to stała wartość, ale użycie mutable słowa kluczowego anuluje to. Nie produkuje modyfikowalnych elementów członkowskich danych.Typically, a lambda's function call operator is const-by-value, but use of the mutable keyword cancels this out. It does not produce mutable data members. Specyfikacja modyfikowalna umożliwia treści wyrażenia lambda modyfikację zmiennych, które są przechwytywane przez wartość.The mutable specification enables the body of a lambda expression to modify variables that are captured by value. W niektórych przykładach w dalszej części tego artykułu pokazano, jak korzystać z programu mutable .Some of the examples later in this article show how to use mutable.

Specyfikacja wyjątkuException Specification

Można użyć noexcept specyfikacji wyjątku, aby wskazać, że wyrażenie lambda nie generuje żadnych wyjątków.You can use the noexcept exception specification to indicate that the lambda expression does not throw any exceptions. Podobnie jak w przypadku funkcji zwykłych, kompilator języka Microsoft C++ generuje ostrzeżenie C4297 , jeśli wyrażenie lambda deklaruje noexcept specyfikację wyjątku i treść lambda zgłasza wyjątek, jak pokazano poniżej:As with ordinary functions, the Microsoft C++ compiler generates warning C4297 if a lambda expression declares the noexcept exception specification and the lambda body throws an exception, as shown here:

// throw_lambda_expression.cpp
// compile with: /W4 /EHsc
int main() // C4297 expected
{
   []() noexcept { throw 5; }();
}

Aby uzyskać więcej informacji, zobacz specyfikacje wyjątków (throw).For more information, see Exception Specifications (throw).

Typ zwracanyReturn Type

Zwracany typ wyrażenia lambda jest automatycznie wywnioskowany.The return type of a lambda expression is automatically deduced. Nie trzeba używać auto słowa kluczowego, chyba że zostanie określony końcowy typ zwracany.You don't have to use the auto keyword unless you specify a trailing-return-type. Końcowy typ zwracany jest podobny do części typu zwracanego zwykłej metody lub funkcji.The trailing-return-type resembles the return-type part of an ordinary method or function. Jednak zwracany typ musi być zgodny z listą parametrów i musi zawierać słowo kluczowe końcowego typu zwracanego -> przed typem zwracanym.However, the return type must follow the parameter list, and you must include the trailing-return-type keyword -> before the return type.

Możesz pominąć część typu zwracanego wyrażenia lambda, jeśli treść lambda zawiera tylko jedną instrukcję return lub wyrażenie nie zwraca wartości.You can omit the return-type part of a lambda expression if the lambda body contains just one return statement or the expression does not return a value. Jeśli treść lambda zawiera jedną instrukcję return, kompilator wywnioskuje typ zwracany z typu wyrażenia Return.If the lambda body contains one return statement, the compiler deduces the return type from the type of the return expression. W przeciwnym razie kompilator wywnioskuje typ zwracany void .Otherwise, the compiler deduces the return type to be void. Rozważmy następujące przykładowe fragmenty kodu, które ilustrują tę zasadę.Consider the following example code snippets that illustrate this principle.

auto x1 = [](int i){ return i; }; // OK: return type is int
auto x2 = []{ return{ 1, 2 }; };  // ERROR: return type is void, deducing
                                  // return type from braced-init-list is not valid

Wyrażenie lambda może generować inne wyrażenie lambda jako wartość zwracaną.A lambda expression can produce another lambda expression as its return value. Aby uzyskać więcej informacji, zobacz sekcję "wyrażenia lambda o wyższej kolejności" w przykładach wyrażeń lambda.For more information, see "Higher-Order Lambda Expressions" in Examples of Lambda Expressions.

Treść lambdaLambda Body

Treść lambda (instrukcja złożona w standardowej składni) wyrażenia lambda może zawierać wszystko, co może zawierać treść zwykłej metody lub funkcji.The lambda body (compound-statement in the Standard syntax) of a lambda expression can contain anything that the body of an ordinary method or function can contain. Treść zwykłej funkcji i wyrażenia lambda może uzyskiwać dostęp do tego rodzaju zmiennych:The body of both an ordinary function and a lambda expression can access these kinds of variables:

  • Przechwycone zmienne z otaczającego zakresu, jak opisano wcześniej.Captured variables from the enclosing scope, as described previously.

  • ParametryParameters

  • Lokalnie deklarowane zmienneLocally-declared variables

  • Elementy członkowskie danych klasy, gdy zadeklarowano wewnątrz klasy i this są przechwytywaneClass data members, when declared inside a class and this is captured

  • Jakakolwiek zmienna, która ma statyczny czas przechowywania — na przykład zmienne globalneAny variable that has static storage duration—for example, global variables

Poniższy przykład zawiera wyrażenie lambda, które jawnie przechwytuje zmienną n według wartości i niejawnie przechwytuje zmienną m według odwołania:The following example contains a lambda expression that explicitly captures the variable n by value and implicitly captures the variable m by reference:

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

int main()
{
   int m = 0;
   int n = 0;
   [&, n] (int a) mutable { m = ++n + a; }(4);
   cout << m << endl << n << endl;
}
5
0

Ponieważ zmienna n jest przechwytywana przez wartość, jej wartość pozostaje 0 po wywołaniu wyrażenia lambda.Because the variable n is captured by value, its value remains 0 after the call to the lambda expression. mutable Specyfikacja może n być modyfikowana w wyrażeniu lambda.The mutable specification allows n to be modified within the lambda.

Mimo że wyrażenie lambda może przechwytywać tylko zmienne, które mają automatyczny czas trwania przechowywania, można używać zmiennych o statycznym czasie trwania przechowywania w treści wyrażenia lambda.Although a lambda expression can only capture variables that have automatic storage duration, you can use variables that have static storage duration in the body of a lambda expression. Poniższy przykład używa generate funkcji i wyrażenia lambda do przypisania wartości do każdego elementu w vector obiekcie.The following example uses the generate function and a lambda expression to assign a value to each element in a vector object. Wyrażenie lambda modyfikuje zmienną statyczną, aby wygenerować wartość następnego elementu.The lambda expression modifies the static variable to generate the value of the next element.

void fillVector(vector<int>& v)
{
    // A local static variable.
    static int nextValue = 1;

    // The lambda expression that appears in the following call to
    // the generate function modifies and uses the local static
    // variable nextValue.
    generate(v.begin(), v.end(), [] { return nextValue++; });
    //WARNING: this is not thread-safe and is shown for illustration only
}

Aby uzyskać więcej informacji, zobacz generowanie.For more information, see generate.

Poniższy przykład kodu używa funkcji z poprzedniego przykładu i dodaje przykład wyrażenia lambda, które używa standardowej biblioteki języka C++ generate_n .The following code example uses the function from the previous example, and adds an example of a lambda expression that uses the C++ Standard Library algorithm generate_n. To wyrażenie lambda przypisuje element vector obiektu do sumy poprzednich dwóch elementów.This lambda expression assigns an element of a vector object to the sum of the previous two elements. mutable Słowo kluczowe jest używane, aby treść wyrażenia lambda mogła zmodyfikować jego kopie zmiennych zewnętrznych x i y , które wyrażenie lambda przechwytuje przez wartość.The mutable keyword is used so that the body of the lambda expression can modify its copies of the external variables x and y, which the lambda expression captures by value. Ponieważ wyrażenie lambda przechwytuje oryginalne zmienne x i y według wartości, ich wartości pozostają 1 po wykonaniu lambda.Because the lambda expression captures the original variables x and y by value, their values remain 1 after the lambda executes.

// compile with: /W4 /EHsc
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>

using namespace std;

template <typename C> void print(const string& s, const C& c) {
    cout << s;

    for (const auto& e : c) {
        cout << e << " ";
    }

    cout << endl;
}

void fillVector(vector<int>& v)
{
    // A local static variable.
    static int nextValue = 1;

    // The lambda expression that appears in the following call to
    // the generate function modifies and uses the local static
    // variable nextValue.
    generate(v.begin(), v.end(), [] { return nextValue++; });
    //WARNING: this is not thread-safe and is shown for illustration only
}

int main()
{
    // The number of elements in the vector.
    const int elementCount = 9;

    // Create a vector object with each element set to 1.
    vector<int> v(elementCount, 1);

    // These variables hold the previous two elements of the vector.
    int x = 1;
    int y = 1;

    // Sets each element in the vector to the sum of the
    // previous two elements.
    generate_n(v.begin() + 2,
        elementCount - 2,
        [=]() mutable throw() -> int { // lambda is the 3rd parameter
        // Generate current value.
        int n = x + y;
        // Update previous two values.
        x = y;
        y = n;
        return n;
    });
    print("vector v after call to generate_n() with lambda: ", v);

    // Print the local variables x and y.
    // The values of x and y hold their initial values because
    // they are captured by value.
    cout << "x: " << x << " y: " << y << endl;

    // Fill the vector with a sequence of numbers
    fillVector(v);
    print("vector v after 1st call to fillVector(): ", v);
    // Fill the vector with the next sequence of numbers
    fillVector(v);
    print("vector v after 2nd call to fillVector(): ", v);
}
vector v after call to generate_n() with lambda: 1 1 2 3 5 8 13 21 34
x: 1 y: 1
vector v after 1st call to fillVector(): 1 2 3 4 5 6 7 8 9
vector v after 2nd call to fillVector(): 10 11 12 13 14 15 16 17 18

Aby uzyskać więcej informacji, zobacz generate_n.For more information, see generate_n.

constexpr wyrażenia lambdaconstexpr lambda expressions

Visual Studio 2017 w wersji 15,3 lub nowszej (dostępne z /std:c++17 ): wyrażenie lambda może być zadeklarowane jako constexpr lub używane w wyrażeniu stałym, gdy Inicjalizacja każdego elementu członkowskiego danych, który przechwytuje lub wprowadza, jest dozwolony w wyrażeniu stałym.Visual Studio 2017 version 15.3 and later (available with /std:c++17): A lambda expression may be declared as constexpr or used in a constant expression when the initialization of each data member that it captures or introduces is allowed within a constant expression.

    int y = 32;
    auto answer = [y]() constexpr
    {
        int x = 10;
        return y + x;
    };

    constexpr int Increment(int n)
    {
        return [n] { return n + 1; }();
    }

Wyrażenie lambda jest niejawnie, constexpr jeśli jego wynik spełnia wymagania constexpr funkcji:A lambda is implicitly constexpr if its result satisfies the requirements of a constexpr function:

    auto answer = [](int n)
    {
        return 32 + n;
    };

    constexpr int response = answer(10);

Jeśli wyrażenie lambda jest niejawnie lub jawne constexpr , konwersja na wskaźnik funkcji generuje constexpr funkcję:If a lambda is implicitly or explicitly constexpr, conversion to a function pointer produces a constexpr function:

    auto Increment = [](int n)
    {
        return n + 1;
    };

    constexpr int(*inc)(int) = Increment;

specyficzne dla firmy MicrosoftMicrosoft-specific

Wyrażenia lambda nie są obsługiwane w następujących jednostkach zarządzanych środowiska uruchomieniowego języka wspólnego (CLR): ref class , ref struct , value class , lub value struct .Lambdas are not supported in the following common language runtime (CLR) managed entities: ref class, ref struct, value class, or value struct.

Jeśli używasz modyfikatora specyficznego dla firmy Microsoft, takiego jak __declspec , możesz wstawić go do wyrażenia lambda bezpośrednio po parameter-declaration-clause — na przykład:If you are using a Microsoft-specific modifier such as __declspec, you can insert it into a lambda expression immediately after the parameter-declaration-clause—for example:

auto Sqr = [](int t) __declspec(code_seg("PagedMem")) -> int { return t*t; };

Aby określić, czy modyfikator jest obsługiwany przez wyrażenia lambda, zobacz artykuł dotyczący tego elementu w sekcji Modyfikatory specyficzne dla firmy Microsoft w dokumentacji.To determine whether a modifier is supported by lambdas, see the article about it in the Microsoft-Specific Modifiers section of the documentation.

Poza standardowymi funkcjami lambda języka C++ 11 program Visual Studio obsługuje bezstanowe wyrażenia lambda, które są zamiennie konwertowane do wskaźników funkcji, które korzystają z dowolnych konwencji wywoływania.In addition to C++11 Standard lambda functionality, Visual Studio supports stateless lambdas, which are omni-convertible to function pointers that use arbitrary calling conventions.

Zobacz teżSee also

Dokumentacja języka C++C++ Language Reference
Obiekty funkcji w standardowej bibliotece języka C++Function Objects in the C++ Standard Library
Wywołanie funkcjiFunction Call
for_each