C++20: Templated Lambda Expressions
Templated lambda expressions allow you to get easy access to type information of generic lambda expression parameters. This also allows you to put constraints on the types of generic lambda expressions parameters. For example, the following generic lambda expression accepts two parameters, both defined with auto type deduction:
[](const auto& a, const auto& b) { /* ... */ }
Since both parameters are auto type deduced, the compiler is free to choose different types for both parameters. If you do not want this, you can use the following templated lambda expression:
[]<typename T>(const T& a, const T& b) { /* ... */ }
This can be combined with C++20 concepts to further constrain type T. For example, you can require that type T is an integral type as follows (needs <concepts>):
[]<std::integral T>(const T& a, const T& b) { /* ... */ }
Using a templated lambda expression, you have direct access to the type of a parameter. Hence, it’s easier to, for example, create a local variable in your lambda expression that has the same type as the type of one of the parameters. Without a templated lambda expression, you would have to involve decltype() and std::decay_t on generic lambda expression parameters to achieve the same thing.
For example, suppose you have a lambda expression accepting a std::vector where the type of the elements can be anything. We can use a generic lambda expression for this. However, if in the body of the lambda, you want to know the exact type of the elements in the vector, you need to use decltype() and decay_t:
[](const auto& v) {
using V = std::decay_t<decltype(v)>; // vector's type
using T = typename V::value_type; // vector element's type
T temp;
/* ... */
}
With a templated lambda expression you can make this much more concise and easier to understand:
[]<typename T>(const std::vector<T>& v) {
T temp;
/* ... */
}
My book, Professional C++, 5th Edition, explains all new C++20 features, and much more.