Working with C++0x/C++11: Lambdas – part 1- Syntax

Lambdas are new to C++0x and if you are familiar with functors then you already have a good idea of how lambdas can be used. Where lambdas really become useful (in my opinion) are allowing you to encapsulate behavior (as a local function) and encapsulate state (as closures). Once you get used to these ideas it gets easier and easier to see instances where you can simplify your code by using lambdas. But we need to crawl before we can walk so let’s start off with some basics. Lambdas in C++ add a lot of power over other language’s versions (Java and C#) because they allow you to not only capture state but to affect state as well. So let’s jump in. The simplest valid lambda expression is the following;

.
    []{}; // in some scope, not global. Valid C++0x code</code>
.

The [] is the lambda-introducer, which tells the compiler that a lambda expression is beginning. It’s also where you can specify the capture-clause, which is the kind of scope-capture you want to use as the default for the lambda. Here it’s empty, so there is no default scope. The {} is the compound-statement, which is the actual local function that you are defining, which uses the variables at the scope that the introducer defined or the parameters passed into the lambda. In this case it’s just an empty function.

There are a lot of modifiers for a lambda, and if you wanted to have all the bells and whistles specified you could write something like this;

.
    // the simplest lambda with all the parts exposed, also valid C++0x code
    [=]() mutable throw()-> void {}();
.

The [=] specifies that the default capture mode is by value. The default [] is to capture nothing. [&] means the default is capture by reference. The first ( ) specifies the parameter-declaration-list, which are the const pass-by-value variable and/or by-reference declarations. Since parameters that are pass-by-value are const, there’s an “mutable” keyword that undoes the const-ness of those parameters.

 
The second ( ) following the throw is the type of exception that this lambda can throw – the default is none. The -> is the return-type-clause, the default return is of type void. This is only necessary if the return type isn’t obvious. The { } defines an lambda body – in this case it’s an empty function.

The last parenthesis at the end are the actual parameters if you wanted to create an instance of the lambda and call it with those parameters. In other words this actually creates a lambda and calls it with those parameters. I just include it for completeness and to totally weird you out with the syntax. It’s legal but usually you’d see that in some stl container iterator implementation where you’re declaring and invoking the lambda in one go.

There are three basic parts to a lambda – the block that describes the scope of the various parameters, the block that describes the return signature of the lambda, and finally the actual compound statement that makes of the lambda body.

In actual use it’s a bit cleaner. Usually there will be the introducer with a capture clause and the compound statement, which is just the lambda (i.e. function) body. The capture scope is where you get a lot of the power of lambdas – plus a lot of opportunity to mess things up if you don’t understand scope capture. That’s what I’ll cover next time.

This entry was posted in C++0X/C++11, Code. Bookmark the permalink.