C++ 14 представил общие лямбды, которые позволили написать следующее:
auto func = [](auto a, auto b){
return a + b;
};
auto Foo = func(2, 5);
auto Bar = func("hello", "world");
Совершенно очевидно, что эта универсальная лямбда-функция func работает так же, как шаблонная функция func.
Почему комитет C++ решил добавить синтаксис шаблона для общей lamda?
Мне сказали, что это - интересный вариант использования.
См. Это для сравнения различных версий лямбда: modernescpp.com/index.php/more-powerful-lambdas-with-c-20





Поскольку вы можете использовать шаблонные лямбды в C++ 20, вы можете ограничить свои типы более простым способом, чем выражение SFINAE:
auto lambda = []<typename T>(std::vector<T> t){};
Эта лямбда будет работать только с векторными типами.
Как consteval связан с новым синтаксисом? Это круто и все такое, но я не понимаю актуальности.
Это больше информация о том, что C++ 20 добавляет к лямбда-выражению, чем ответ на вопрос
предложение, который был принят в C++ 20, имеет длинный раздел мотивации с примерами. Предпосылка этого такова:
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.
После этого довольно много примеров.
Общие лямбда-выражения C++ 14 - это очень крутой способ сгенерировать функтор с operator (), который выглядит следующим образом:
template <class T, class U>
auto operator()(T t, U u) const;
Но не так:
template <class T>
auto operator()(T t1, T t2) const; // Same type please
Не так:
template <class T, std::size_t N>
auto operator()(std::array<T, N> const &) const; // Only `std::array` please
И не так (хотя на самом деле это немного сложно использовать):
template <class T>
auto operator()() const; // No deduction
Лямбда-выражения C++ 14 подходят, но C++ 20 позволяет нам без проблем реализовать эти случаи.
Красиво и лаконично. Просто добавив это: первый (те же типы) может быть решен с помощью (auto a, decltype(a) b) в C++ 14.
@SebastianMach почти. С этим решением b не выводится, и вместо этого его аргумент будет неявно преобразован в тип a.
The new "familiar template syntax" for lambdas introduced in C++20 makes constructs such as
for_typesandfor_rangeviable and way more readable compared to C++17 alternatives.
(источник: итерация во время компиляции с лямбда-выражениями C++ 20)
Еще одна интересная вещь, которую можно сделать в общих лямбда-выражениях C++ 14 и C++ 17, - это прямой вызов operator() путем явной передачи параметра шаблона:
C++ 14:
auto l = [](auto){ };
l.template operator()<int>(0);
C++ 20 (см. Также объяснение для <tparams>на cppreference):
auto l = []<typename T>(){ };
l.template operator()<int>();
Приведенный выше пример C++ 14 совершенно бесполезен: нет способа сослаться на тип, предоставленный operator() в теле лямбда-выражения, без указания имени аргумента и использования decltype. Кроме того, мы вынуждены передавать аргумент, даже если он нам может не понадобиться.
В примере C++ 20 показано, как легко получить доступ к T в теле лямбда-выражения и что теперь можно произвольно создавать шаблоны для лямбда-выражения с нулевым значением. Это будет очень полезно для реализации вышеупомянутых конструкций времени компиляции.
Что делать, если вам нужно использовать тип шаблона разные, а не для аргументов или типа возвращаемого значения? А если это нужно внутри тела?