As you’ll see in this chapter, many Standard Library algorithms can receive function pointers as parameters—recall from Section 12.8 that the name of a function is implicitly convertible into a pointer to that function’s code. Before you can pass a function pointer to an algorithm, the corresponding function must be declared.
C++11’s lambda expressions (or simply lambdas) enable you to define anonymous functions where they’re passed to a function. They’re defined locally inside functions and can use and manipulate the local variables of the enclosing function. Figure 16.1 demonstrates the Standard Library’s for_each
algorithm, which invokes a function once for each element in a range. The example calls for_each
twice, each with a simple lambda:
the first is used to display each element in an int
array
multiplied by 2.
the second is used to sum the elements of the int
array
.
for_each
Lines 19–20 and 24 use the for_each
algorithm to call a function that performs a task once for each element of the array values
. Like the algorithm copy
(introduced in Section 15.3), for_each
’s first two arguments represent the range of elements to process. This program processes from values.cbegin()
(the position of the array
’s first element) up to, but not including, values.cend()
(the position one past the array
’s last element), so all of the array
’s elements are processed. The for_each
algorithm’s two iterator arguments must be at least input iterators that point into the same container, so for_each
can get values from that container.
The function specified by for_each
’s third argument specifies the function to call with each element in the range. The function must have one parameter of the container’s element type. for_each
passes the current element’s value as the function’s argument, then the function performs a task using that value. As you’ll see momentarily, this example’s for_each
calls each receive as their third argument a lambda representing a function that receives one argument and performs a task with that argument’s value. If the function’s parameter is a non-const
reference and the iterators passed to for_each
refer to non-const
data, the function can modify the element.
Line 11 declares and initializes the array
of int
s named values
and line 15 displays its contents. Lines 19–20 call the for_each
algorithm to multiply each element of values
by 2 and display the result. The third argument (line 20) to for_each
[](auto i) {cout << i * 2 << " ";}
is a lambda expression that performs the multiplication and output.
Lambdas begin with the lambda introducer ([]
), followed by a parameter list and function body. A lambda can use local variables from the function in which the lambda is defined. The introducer enables you to specify which, if any, local variables the lambda uses—this is known as capturing the variables. The empty lambda introducer ([]
) in line 20 indicates that the lambda does not use any of main
’s local variables.
The lambda in line 20 receives one parameter named i
. Specifying the parameter’s type as auto
enables the compiler to infer the parameter’s type, based on the context in which the lambda appears. In this case, the for_each
algorithm calls line 20’s lambda once for each element of the array
, passing the element’s value as the lambda’s argument. Since the array
contains int
s, the compiler infers parameter i
’s type as int
. Using auto
to infer the parameter type is a new C++14 feature of so-called generic lambdas. In C++11 you were required to state each lambda parameter’s explicit type. In this example, the lambda in line 20 is similar to the standalone function
void timesTwo(int i) {
cout << i * 2 << " ";
}
Had we defined this function, lines 19–20 could have called the for_each
algorithm with timesTwo
’s function name as the third argument, as in
for_each(values.cbegin(), values.cend(), timesTwo);
The second call to the for_each
algorithm (line 24) totals array
’s elements. The lambda introducer [&sum]
in
[&sum](auto i) {sum += i;}
indicates that this lambda expression captures the local variable sum
(line 23) by reference. The ampersand (&
) indicates that the lambda captures sum
by reference and can modify its value. Without the ampersand, sum
would be captured by value and the lambda would not modify the local variable outside the lambda expression. The for_each
algorithm passes each element of values
to the lambda, which adds the value to the sum
. Line 26 then displays the sum
.
The compiler can infer a lambda’s return type if the body contains a statement of the form
return expression;
Otherwise, the lambda’s return type is void
, unless you explicitly specify a return type using C++11’s trailing return type syntax (-> type
), as in
[](parameterList) -> type {lambdaBody}
The trailing return type is placed between the parameter list’s closing right parenthesis and the lambda’s body.