What is the need of template lambda introduced in C++20 when C++14 already has generic lambda?

introduced generic lambdas that made it possible to write following:

auto func = [](auto a, auto b){
return a + b;
};
auto Foo = func(2, 5);
auto Bar = func("hello", "world");

It is very clear that this generic lambda func works just like a templated function func would work.

Why did the C++ committee decide to add template syntax for generic lamda?

12323 次浏览

Since you can use templated lambdas in C++20, you can restrict your types in an easier way than an SFINAE expression:

auto lambda = []<typename T>(std::vector<T> t){};

This lambda will work only with vector types.

The proposal that was accepted into C++20 has a lengthy motivation section, with examples. The premise of it is this:

There are a few key reasons why the current syntax for defining generic lambdas is deemed insufficient by the author. The gist of it is that some things that can be done easily with normal function templates require significant hoop jumping to be done with generic lambdas, or can’t be done at all.The author thinks that lambdas are valuable enough that C++ should support them just as well as normal function templates.

Following that are quite a few examples.

C++14 generic lambdas are a very cool way to generate a functor with an operator () that looks like this:

template <class T, class U>
auto operator()(T t, U u) const;

But not like this:

template <class T>
auto operator()(T t1, T t2) const; // Same type please

Nor like this:

template <class T, std::size_t N>
auto operator()(std::array<T, N> const &) const; // Only `std::array` please

Nor like this (although this gets a bit tricky to actually use):

template <class T>
auto operator()() const; // No deduction

C++14 lambdas are fine, but C++20 allows us to implement these cases without hassle.

The new "familiar template syntax" for lambdas introduced in C++20 makes constructs such as for_types and for_range viable and way more readable compared to C++17 alternatives.

(source: compile-time iteration with C++20 lambdas)

Another interesting thing that can be done on both C++14 and C++17 generic lambdas is directly calling operator() by explicitly passing a template parameter: C++14:

auto l = [](auto){ };
l.template operator()<int>(0);

C++20 (see also the explanation for <tparams> on cppreference):

auto l = []<typename T>(){ };
l.template operator()<int>();

The C++14 example above is quite useless: there's no way of referring to the type provided to operator() in the body of the lambda without giving the argument a name and using decltype. Additionally, we're forced to pass an argument even though we might not need it.

The C++20 example shows how T is easily accessible in the body of the lambda and that a nullary lambda can now be arbitrarily templated. This is going to be very useful for the implementation of the aforementioned compile-time constructs.