Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic C++14 lambdas and relationship with templates

Tags:

c++

lambda

c++14

I did read that C++14 generic lambdas with auto parameters are actually templates, so the following is valid C++14

auto glambda = [] (auto a) { return a; };
cout << glambda(23); // Prints 23
cout << glambda('A'); // Prints A

This doesn't quite stack up with what I know from templates.. where's the instantiation point? What is it stored in the glambda variable if the first call instantiates a template with int and the second one with char?

like image 462
Dean Avatar asked Dec 14 '22 06:12

Dean


2 Answers

It's not that the "lambda is a template" -- that doesn't make sense, a lambda is an expression. Rather, the type of the closure object that's defined by the lambda expression has an overloaded function call operator that is defined by a member function template. So the instantiation point is the first use of the respective call operator.

In other words, a lambda [a, &b](auto x, auto y) -> R { /* ... */ } has a type like:

struct __lambda
{
    __lambda(const A & __a, B & __b) : a(__a), b(__b) {}

    template <typename T1, typename T2>
    R operator()(T1 x, T2 y) const { /* ... */ }

private:
    A a;
    B & b;
};
like image 172
Kerrek SB Avatar answered Dec 29 '22 08:12

Kerrek SB


A generic lambda is an object of a compiler generated type that has a template method called operator(). Your code can be rewritten with this equivalent:

struct MyLambda {
    template<typename T>
    T operator() (T val) {
        return val;
    }
};

int main() {
    MyLambda func;

    std::cout << func('A');
    std::cout << func(42);
}

The compiler will instantiate operator() when needed.

Hope it helped

like image 35
Guillaume Racicot Avatar answered Dec 29 '22 07:12

Guillaume Racicot