Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lambda functions with template parameters, not in function parameters

Why does the first call not compile?

auto get1 = []<int B>() { return B; };
auto get2 = []<typename B>(B b) { return b; };

int main()
{
    get1<5>(); // error: no match for operator<
    get2(5);   // ok
}

The reason I use this, is an expression repeated many times in code.

Of course I can use a real function template, but just I am curious WHY.

like image 570
Chameleon Avatar asked Feb 04 '23 17:02

Chameleon


1 Answers

This is easier to understand if you consider what the equivalent class type looks like to your get1:

struct get1_t {
    template <int B> operator()() const { return B; }
};

get1_t get1;

get1<5>(); // error

You're trying to provide an explicit template parameter to the call operator, but syntactically you're doing what looks like providing template parameters for get1 itself (i.e. as if get1 were a variable template). In order to provide the template parameter for the call operator, you have to do that directly:

get1.operator()<5>(); // ok

Or restructure the call operator to take something deducible:

template <int B> struct constant { };
get1(constant<5>{});

Or restructure the whole thing to actually be the variable template that it looks like it is:

template <int B>
auto get1 = [] { return B; };

Now, get1<5> is itself a lambda, that you're invoking. That is, rather than a lambda with a call operator template we have a variable template lambda that is itself not a template.

like image 200
Barry Avatar answered Feb 06 '23 11:02

Barry