Lambda Expressions
The C++ library offers a number of algorithms that take functions as arguments. A typical such algorithm is find_if, which searches a sequence to find the first element (if any) for which a function yields true (that is, a nonzero value). For example, here is a function that finds the first nonempty element in a vector<string>:
bool check_nonempty(const string& s) {
return !s.empty();
}
vector<string>::iterator nonempty(vector<string>& vs)
{
return find_if(vs.begin(), vs.end(), check_nonempty);
}
This function uses an auxiliary function named check_nonempty, which takes a string and yields false if the string is empty and true otherwise. The check_nonempty function is ungainly to write, especially if we intend to use it only once. C++0x allows us to write this kind of nearly trivial function without giving it a name:
vector<string>::iterator nonempty(vector<string>& vs)
{
return find_if(vs.begin(), vs.end(),
[](const string& s) { return !s.empty(); });
}
The syntax that tips us off to this new feature is the use of [], pronounced lambda, which introduces a nameless function as an expression. In this example, we don't need to supply a return type: The function body is just a return statement, so the compiler figures out the type.
To see how this usage can rise beyond mere convenience, consider how we would change our function to find the first string longer than a given length. Many programmers' first thought would be along the following lines:
// <i>This code uses a global variable. Yuck!</i>
unsigned len;
bool check_length(const vector<string>& vs)
{
return vs.size() > len;
}
vector<string>::iterator
longer_than(vector<string>& vs, unsigned n)
{
len = n;
return find_if(vs.begin(), vs.end(), check_length);
}
To pass check_length to find_if, we have had to resort to using a global variable to store the length against which we intend to compare. In theory, we could avoid this global variable by defining an appropriate function object, and we shall leave that approach to those of our readers who wish to see for themselves what a nuisance that alternative is to write.
Lambda gives us the ability to write such auxiliary functions without using a global variable and without the hassle of defining a special-purpose function-object class:
vector<string>::iterator
longer_than(vector<string>& vs, unsigned n)
{
return find_if(vs.begin(), vs.end(),
[=](const string& s) { return s.size() > n; });
}
The = inside the brackets gives this lambda the ability to capture the values of variables in the surrounding context. In effect, what gets passed to find_if is a function object that incorporates the current value of n. What find_if returns is an iterator referring to the first string with more than n characters, or vs.end() if no such string exists.
Conclusion
We have described three C++0x features that make it easier to write code that uses the standard library. The first one, data movement, often operates invisibly behind the scenes, allowing our programs to move data from one place to another instead of copying it and then destroying the original. The second, smart pointers, makes it easier to manage memory. The third gives us an easier way to write those little functions that we often need to pass as arguments to library functions.
Our final article in this series will talk about how C++0x gives library authors more detailed control over the classes they define.


