Зачем нужен шаблон лямбда, введенный в C++ 20, если в 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?

Что делать, если вам нужно использовать тип шаблона разные, а не для аргументов или типа возвращаемого значения? А если это нужно внутри тела?

Some programmer dude 10.01.2019 11:07

Мне сказали, что это - интересный вариант использования.

Max Langhof 10.01.2019 11:21

См. Это для сравнения различных версий лямбда: modernescpp.com/index.php/more-powerful-lambdas-with-c-20

schoetbi 24.08.2020 08:29
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
107
3
10 537
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Поскольку вы можете использовать шаблонные лямбды в C++ 20, вы можете ограничить свои типы более простым способом, чем выражение SFINAE:

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

Эта лямбда будет работать только с векторными типами.

Как consteval связан с новым синтаксисом? Это круто и все такое, но я не понимаю актуальности.

StoryTeller - Unslander Monica 10.01.2019 11:14

Это больше информация о том, что C++ 20 добавляет к лямбда-выражению, чем ответ на вопрос

Antoine Morrier 10.01.2019 11:14

предложение, который был принят в 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.

Sebastian Mach 11.01.2019 11:05

@SebastianMach почти. С этим решением b не выводится, и вместо этого его аргумент будет неявно преобразован в тип a.

Quentin 11.01.2019 11:07

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.

(источник: итерация во время компиляции с лямбда-выражениями 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 в теле лямбда-выражения и что теперь можно произвольно создавать шаблоны для лямбда-выражения с нулевым значением. Это будет очень полезно для реализации вышеупомянутых конструкций времени компиляции.

Другие вопросы по теме