Generic Lambda in C++ 14

Share the Article

Generic Lambda in C++ 14 is a feature similar to templates. This was not present in C++11. In particular, the Generic lambda have auto in their parameter specification. This lambda can accept argument of any datatype, and indeed this is similar to templates.

The example showing this is as follows:

#include <iostream> //main header using namespace std; //namespace void funda(int xvar) { cout << "funda(int)" << endl; } void funda(double xvar) { cout << "funda(double)" << endl; } int main() { auto lambda = [](auto arg) { funda(arg); }; int ivar = 9; lambda(ivar); lambda(4); float jvar = 3.2; lambda(jvar); lambda(3.4); return 0; }

Output:

Lambda with auto argument type in C++14

The C++11 compiler will not recognize this format.

Lambda with auto argument not allowed in C++11

Similar to template class

The generic lambda will have following template equivalent.

#include <iostream> //main header using namespace std; //namespace void funda(int xvar) { cout << "funda(int)" << endl; } void funda(double xvar) { cout << "funda(double)" << endl; } template<typename T> void lambda(T arg) { funda(arg); } int main() { // auto lambda = [](auto arg) // { // funda(arg); // }; int ivar = 9; lambda(ivar); lambda(4); float jvar = 3.2; lambda(jvar); lambda(3.4); return 0; }
Lambda with auto argument type similar to template class

Generic lambda equivalent to Universal reference

To make a generic lambda equivalent to universal reference based template functions, following 3 conditions should be fulfilled.

  1. The parameter specification of lambda contains auto&&.
  2. Lambda shall use std::forward to forward the argument to either L-value or R-value overload
  3. std::forward shall use decltype of argument passed

auto&&

The semantics of auto&& is similar to universal reference template parameter, i.e., T&&. In such case, it will use reference collapsing rules to deduce the actual parameter type. This means, if an L-value argument is passed to lambda, then argument will deduce to become L-value reference. Similarly, it will become R-value reference when an R-value is passed as argument.

std::forward(decltype(arg)>

When parameter deduces to become an L-value reference, then std::forward shall forward it to L-value overload. This is because, in this case, the type specifier, decltype(arg) will return L-value type.

Similarly, when parameter deduces to become an R-value reference, then std::forward’s type specifier decltype(arg) shall return R-value type. Therefore, std::forward function shall forward the argument to R-value overload.

The following example demonstrates this

#include <iostream> //main header using namespace std; //namespace void funda(int& xvar) { cout << "funda(int&)" << endl; } void funda(int&& xvar) { cout << "funda(int&&)" << endl; } int main() { auto lambda = [](auto&& arg) { funda( std::forward<decltype(arg)>(arg) ); }; int ivar = 9; lambda(ivar); //L-value passed lambda(4); //R-value passed return 0; }

In first place, “i” is of L-value type “int&”, therefore, auto&&arg deduces to final type as shown:

auto&& arg => int& && arg => int& arg

In second place “4” is of R-value type “int&&”, therefore, auto&&arg deduces to final type as shown:

auto&& arg => int&& && arg => int&& arg

The output therefore, is as follows:

Lambda with auto&& argument type

Similar to template function based on Universal reference

The following program is exactly equivalent to above lambda.

#include <iostream> //main header using namespace std; //namespace void funda(int& xvar) { cout << "funda(int&)" << endl; } void funda(int&& xvar) { cout << "funda(int&&)" << endl; } template<typename T> void lambda(T&& arg) { fun( std::forward<T>(arg) ); } int main() { //auto lambda = [](auto&& arg) // { // funda(std::forward<decltype(arg)>(arg)); // }; int ivar = 9; lambda(ivar); lambda(4); return 0; }

Output

Lambda with auto&& argument type is similar to universal reference

Main Funda: Generic Lambda in C++ 14 is equivalent to template function

Related Topics:

Lambda in C++11
Lambda in C++17
What are the drawbacks of using enum ?
Which member functions are generated by compiler in class?
How to stop compiler from generating special member functions?
Compiler Generated Destructor is always non-virtual
How to make a class object un-copyable?
Why virtual functions should not be called in constructor & destructor ?
Explaining C++ casts
How pointer to class members are different ?
How std::forward( ) works?
Rule of Three
How std::move() function works?
What is reference collapsing?
How delete keyword can be used to filter polymorphism
emplace_back vs push_back

Share the Article

Leave a Reply

Your email address will not be published. Required fields are marked *