What is the need of template lambda introduced in C++20 when C++14 already has generic lambda?
C++C++14C++20Generic LambdaC++ Problem Overview
[tag:c++14] 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?
C++ Solutions
Solution 1 - C++
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.
Solution 2 - C++
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.
Solution 3 - C++
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.
Solution 4 - C++
> 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.