C++11 Lambdas

C++11 bring in the concept of 'lambdas' (an advanced C++ concept), which allow the definition of inline functions and can be used as a parameter or local object. Lambdas transform the way the C++ standard library was used earlier. Here in this tutorial, it is explained how to implement lambdas and demonstrate how to use lambdas for defining code that can run in parallel.

Syntax of Lambdas

A 'Lambda' can be defined as a definition of functionality which can be definite inside statements and expressions. So, programmers can use a lambda as an inline function. The minimal lambda function contains no parameters.

Example:
[] {
    std::cout << "Welcome Lambda" << std::endl;
}

Programmers' can call them directly like this:

[] {
    std::cout << "Welcome lambda" << std::endl;
}(); // it will print Welcome lambda

or can be passed to objects to get called:

auto lmda = [] {
    std::cout << "Welcome lambda" << std::endl;
};
....lmda(); // prints Welcome lambda

Now you can see that a lambda always begins with a 'lambda introducer': brackets wherein you can specify what is called as 'capture' for accessing non-static objects inside the lambda. When no requirement is there to get access to outside data, the brackets remain empty, as is the case above. You can specify parameters as mutable, an exception specification and the return type. Thus, the syntax of a lambda is either:

[...] {...}

Or you can write:

[...] (...) mutableopt throwSpecopt ->retTypeopt {...}

A lambda can provide parameters particularly in parentheses, similarly to any other function:

auto lmda = [](const std::string& str) {
    std::cout << str << std::endl;
};
lmda("Welcome lambda"); // It print hello lambda

It is to be noted that lambdas cannot be templates. A lambda can also return something. Example, the return type of lambda given below is int:

[] {
    return 62;
}

Captures (Access to Outer Scope)

Inside a lambda introducer (i.e. brackets in the beginning of lambda), programmer's can state a capture for accessing data of outer scope which is not passed as argument:

  • [=] means that the outer scope is accepted to the lambda by value.
  • [&] means the outer scope gets passed to the lambda via reference. So, programmers can limit the access. Example, the following statements becomes:
int a = 0;
int b = 52;
auto ggg = [a, &b] {
    std::cout << "a: " << a << std::endl;
    std::cout << "b: " << b << std::endl;
    ++b; // OK
};
a = b = 67;
ggg();
ggg();
std::cout << "final b: " << b << std::endl;

Different forms of Lambdas

All types of lambda are anonymous function objects which are unique for all lambda expression. So, for declaring objects of this type, programmers need templates or auto. When programmers need the type, they can use decltype().

Alternatively, you can implement the "std::function<> class template" which is done by the C++ standard library for specifying a general type of functional programming. Which means class template provides the only way for specifying the return type of any function returning a lambda:

Example:
#include<functional>
#include<iostream>
std::function<float(float, float)> returnLambda()
{
    return [](float a, float b) {
        return a + b;
    };
}
int main()
{
    auto lmbda = returnLambda();
    std::cout << lmbda(8.2, 6.4) << std::endl;
}