RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Lambda Functions Are Ready for Prime Time-3 : Page 3


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 want—copy or reference—by 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;}); 

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

Danny Kalev is a certified system analyst and software engineer specializing in C++. He was a member of the C++ standards committee between 1997 and 2000 and has since been involved informally in the C++0x standardization process. He is the author of "The ANSI/ISO Professional C++ Programmer's Handbook" and "The Informit C++ Reference Guide: Techniques, Insight, and Practical Advice on C++."
Email AuthorEmail Author
Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date