Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does generic lambda work in C++14?

People also ask

What is generic lambda in C++?

Generic lambda was introduced in the C++14 standard. Conceptually, a generic lambda is equivalent to a function object with a templatized function-call operator method: struct LambdaClosureType { ... template<template-params> ret operator()(params) const { ... } .... };

How does lambda work C++?

A lambda can introduce new variables in its body (in C++14), and it can also access, or capture, variables from the surrounding scope. A lambda begins with the capture clause. It specifies which variables are captured, and whether the capture is by value or by reference.

Is lambda expression Cannot be generic?

A lambda expression can't specify type parameters, so it's not generic. However, a functional interface associated with lambda expression is generic. In this case, the target type of lambda expression has determined by the type of argument(s) specified when a functional interface reference is declared.

Is there lambda function in C?

Significance of Lambda Function in C/C++ Lambda Function − Lambda are functions is an inline function that doesn't require any implementation outside the scope of the main program. Lambda Functions can also be used as a value by the variable to store.


Generic lambdas were introduced in C++14.

Simply, the closure type defined by the lambda expression will have a templated call operator rather than the regular, non-template call operator of C++11's lambdas (of course, when auto appears at least once in the parameter list).

So your example:

auto glambda = [] (auto a) { return a; };

Will make glambda an instance of this type:

class /* unnamed */
{
public:
    template<typename T>
    T operator () (T a) const { return a; }
};

Paragraph 5.1.2/5 of the C++14 Standard Draft n3690 specifies how the call operator of the closure type of a given lambda expression is defined:

The closure type for a non-generic lambda-expression has a public inline function call operator (13.5.4) whose parameters and return type are described by the lambda-expression’s parameter-declaration-clause and trailing-return-type respectively. For a generic lambda, the closure type has a public inline function call operator member template (14.5.2) whose template-parameter-list consists of one invented type template-parameter for each occurrence of auto in the lambda’s parameter-declaration-clause, in order of appearance. The invented type template-parameter is a parameter pack if the corresponding parameter-declaration declares a function parameter pack (8.3.5). The return type and function parameters of the function call operator template are derived from the lambda-expression’s trailing-return-type and parameter-declarationclause by replacing each occurrence of auto in the decl-specifiers of the parameter-declaration-clause with the name of the corresponding invented template-parameter.

Finally:

Is it similar to templates where for each different argument type compiler generates functions with the same body but changed types or is it more similar to Java's generics?

As the above paragraph explains, generic lambdas are just syntactic sugar for unique, unnamed functors with a templated call operator. That should answer your question :)


Unfortunately, they are not part of C++11 (http://ideone.com/NsqYuq):

auto glambda = [](auto a) { return a; };

int main() {}

With g++ 4.7:

prog.cpp:1:24: error: parameter declared ‘auto’
...

However, the way it might be implemented in C++14 as per the Portland proposal for generic lambdas:

[](const& x, & y){ return x + y; }

This would yield for the biggest part the usual creation of an anonymous functor class, but with the lack of types the compiler would emit a templated member-operator():

struct anonymous
{
    template <typename T, typename U>
    auto operator()(T const& x, U& y) const -> decltype(x+y)
    { return x + y; }
};

Or as per the newer proposal Proposal for Generic (Polymorphic) Lambda Expressions

auto L = [](const auto& x, auto& y){ return x + y; };

--->

struct /* anonymous */
{
    template <typename T, typename U>
    auto operator()(const T& x, U& y) const // N3386 Return type deduction
    { return x + y; }
} L;

So yes, for every permutation of parameters, a new instantiation would arise, however, the members of that functor would still be shared (i.e. the captured arguments).


It's a proposed C++14 feature (not in C++11) similar (or even equivalent) to templates. For instance, N3559 provides this example:

For example, this generic lambda-expression containing statement:

auto L = [](const auto& x, auto& y){ return x + y; };

might result in the creation of a closure type, and object that behaves similar to the struct below:

struct /* anonymous */
{
    template <typename T, typename U>
    auto operator()(const T& x, U& y) const // N3386 Return type deduction
    { return x + y; }
} L;