External References
Roughly speaking, lambda expressions are divided into two categories: those with external references and those with no external references. What it's all about? Lambda expressions with external references access variables defined outside the lambda expression's parameter list. By contrast, lambda expressions with no external references don't access variables defined outside the lambda expression's parameter list. Here's a lambda expression with no external references:
[](int x, int y) -> int { return x + y; }
And here's one with external references:
//Note: pseudo C++ code
int z;
myfunc([](int x, int y)->int {return x + y + z;});
The last lambda accesses the variable
z which is declared outside the lambda expression. In cases like this, the referenced external variable must be represented in the closure somehow. There are two ways in which C++ can store variables with external references in the closure:
- Store a copy of z in a data member.
- Define a reference data member and bind it to z.
You instruct the compiler which type of representation you wantcopy or referenceby providing a lambda capture. A lambda capture is a description of the environment that the lambda expression will access, where the environment is the closure's data members. The capture appears between the brackets of the introducer. There are several types of captures but I'll demonstrate only two of them:
- The default capture [=] indicates that, by default, closure copies the values of the external variables into its private data members.
- The default capture [&] indicates that, by default, closure contains reference variables bound to the external variables.
Following this discussion, you now know that the correct syntax for the last lambda expression is either:
int z;
myfunc([=](int x,int y)->int {return x + y + z;});
or:
int z;
myfunc([&](int x,int y)->int {return x + y + z;});
Depending on whether you want the closure to store a copy of
z or a reference to it, respectively.
Getting back to the original example, you can tell what the role of the [&] in the following lambda is:
double min_salary = 1000;
double upper_lmt = 1.5 * min_salary;
std::find if(emps.begin(), emps.end(),
[&](const employee& emp)
(emp.salary() >= min_salary && emp.salary()&lr upper_lmt));
The body refers to the variables
min_salary and
upper_lmt, which are declared independently of the lambda expression. The lambda introducer contains the
& capture which instructs the compiler to create reference data members that are bound to
min_salary and
upper_lmt. As you can see, lambda functions are likely to simplify your code.
At the time of writing, several compilers including Visual C++ 10 (beta) and Intel C++ 11.0 already support lambdas. Others are soon likely to follow suit