У чому полягає потреба шаблону лямбда, введеного в C ++ 20, коли в C ++ 14 уже є загальна лямбда?


99

представив загальні лямбди, які дали можливість писати наступне:

auto func = [](auto a, auto b){
    return a + b;
};
auto Foo = func(2, 5);
auto Bar = func("hello", "world");

Цілком зрозуміло, що ця загальна лямбда funcпрацює так само, як працює шаблонна функція func.

Чому комітет C ++ вирішив додати синтаксис шаблону для загальної lamda?


5
Що робити, якщо вам потрібно використовувати інший тип шаблону, ніж для аргументів або типу повернення? А що, якщо це потрібно всередині організму?
Якийсь чувак-програміст

Мені сказали, що це був цікавий випадок використання.
Макс Ланггоф

Подивіться це для порівняння різних версій лямбда: modernescpp.com/index.php/more-powerful-lambdas-with-c-20
schoetbi

Відповіді:


115

Узагальнені лямбди на 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 дозволяє нам реалізовувати ці випадки без клопоту.


2
Приємно і лаконічно. Просто додавши це: Перші (ті самі типи) можна вирішити за допомогою (auto a, decltype(a) b)C ++ 14.
Себастьян Мах,

13
@SebastianMach майже. З цим рішення bне виводиться, і його аргумент буде неявно перетворений у тип aзамість цього.
Квентін

32

Оскільки ви можете використовувати шаблонні лямбди в C ++ 20, ви можете обмежити свої типи простіше, ніж вираз SFINAE:

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

Ця лямбда працюватиме лише з векторними типами.


8
Як constevalпов’язаний новий синтаксис? Це круто і все, але я не отримую актуальності.
StoryTeller - Unslander Monica

Це більше інформація про те, що C ++ 20 додає до лямбда-виразу, ніж відповідь на запитання
Антуан Моррі

24

Пропозиція , яка була прийнята в C ++ 20 має тривалий розділ мотивації, з прикладами. Передумовою цього є:

Є кілька ключових причин, чому чинний синтаксис для визначення загальних лямбда вважається автором недостатнім. Суть цього полягає в тому, що деякі речі, які можна легко зробити за допомогою нормальних шаблонів функцій, вимагають значного стрибка обруча з загальними лямбдами або взагалі не можуть бути зроблені. Автор вважає, що лямбди є досить цінними, щоб C ++ мав їх підтримувати так само, як і звичайні шаблони функцій.

Далі наведено чимало прикладів.


21

Новий "знайомий синтаксис шаблону" для лямбда, введений в C ++ 20, робить такі конструкції як  for_types і  for_range життєздатними, і набагато читабельнішими порівняно з альтернативами C ++ 17.

(джерело: ітерація під час компіляції з лямбдами C ++ 20 )

Ще одна цікава річ, яку можна зробити як на загальних лямбдах C ++ 14, так і на C ++ 17, - це прямий виклик  operator() , явно передавши параметр шаблону:

C ++ 14:

   auto l = [](auto){ };
   l.template operator()<int>(0);

C ++ 20:

  auto l = []<typename T>(){ };
  l.template operator()<int>();

Наведений вище приклад C ++ 14 абсолютно марний: немає жодного способу посилатися на тип, наданий  operator() в тілі лямбда, не вказавши аргументу ім’я та не використовуючи  decltype. Крім того, ми змушені висловити аргумент, хоча він нам може і не знадобитися.

Приклад C ++ 20 показує, як T легко доступний в тілі лямбда-сигналу, і що ядерну лямбду тепер можна довільно шаблонувати. Це буде дуже корисно для реалізації згаданих конструкцій часу компіляції

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.