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

C++C++14C++20Generic Lambda

C++ 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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questioncoder3101View Question on Stackoverflow
Solution 1 - C++QuentinView Answer on Stackoverflow
Solution 2 - C++Antoine MorrierView Answer on Stackoverflow
Solution 3 - C++StoryTeller - Unslander MonicaView Answer on Stackoverflow
Solution 4 - C++Hamza.SView Answer on Stackoverflow