Sunday, August 14, 2011

Lambda (C++11)

Lambda expression is another new thing in C++11

Lambda expression allow you to create a local (temporary) function. And it works like a function pointer or function object.

They look complex and different, But they are not.
All lambda expression start with a capture clause, Following with parameter list, then return type and last the execution scope. If return type is not specified it will try to figure it out it self or use void.

[]() -> bool { return false; };
(A lambda that does nothing. It just returns false.)

[&nCount](int x) -> bool 
{ 
  if(x) 
    return false; 
  else 
    return true; 
};
(A lambda that capture the nCount variable from local scope as a reference, It will accept a int as parameter and will return a bool )


The Lambda expression is generated by the compiler and it is given a unique type name.
But with the auto keyword you can store an lambda function in a variable.

int nCount = 30;

auto lambda = [&nCount](int x) 
{ 
  nCount = nCount + x; 
};

lambda(20);

// nCount is now 50

To capture varibles using by value (copy) you leave out the &,
[nCount](int x) 
{ 
  nCount = nCount + x; 
};
(Changing nCount here will not change the original nCount, since nCount was sent by value)

You can also let the compiler figure out what variable from outside the lambda it should capture.

[&](int x) { ... }; // Capture ALL variables that we need as reference.
[=](int x) { ... }; // Capture ALL variables that we need by value.

// It is also possible to mix it up
[&, nCount](int x) { ... }; // Capture ALL variables that we need by reference
                            // except nCount that will be captured by value.

When to use Lambdas
Lambda are really useful for a lot of STL algorithms that takes predicates and function objects.
like for_each, sort and more. But this is just the beginning. If you plan to use the concurrency framework, AMP, and a lot more that are coming, They will also accept lambdas.

Lambdas is a powerful tool and more and more libraries will support it. So you better get used to them.
They are here to stay.

What lambdas can't be used for
You can not write a normal member function that accept a lambda. Since the type of a lambda is generated at compile time you can not create a normal function to accept a lambda. Since you must specify the type.
templates are able to take lambdas as parameters, But you might not want to wrap you existing code into a template class just to be able to accept a lambda.

There is one workaround, and it is to have your function to accepts a std::function object as parameter instead.

bool myclass:myfunction(std::function<bool(int)> funcobj)
{
  return func(10);
}

....

obj.myfunction( [](int x) -> bool { 
 if(x > 5) 
   return true;
 return false;
} ); 
A lambda can be assigned to a std::function, You will however suffer a bit in performance by going through the std::function code. But it will solve the problem.

But there is a bug.
A lambda that does not capture any variables should be able be assigned to a function pointer of the same types.
But there is a bug in Visual Studio 2010 that does not allows this.
Bug Report

This will be fixed for the next version of Visual Studio.

More Information
There are a lot more tricks with lambdas but I'm stopping here for now.

If you want to learn more check out this pages
Wikipedia
Visual C++ Team Blog
MSDN

No comments:

Post a Comment