Channels ▼
RSS

C/C++

3 Most Useful Library Features of C++0x


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.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video