ограничения и использование лямб-ов шаблонов C ++ 20

Пара связанных вопросов для гуру стандартов C ++.

Входящая в C ++ 20 вводит лямбда-выражения шаблонов (P0428R2).

Так что вместо

auto x = [](auto x, auto y){ return x+y; };

мы можем указать параметр шаблона следующим образом

auto x = []<typename T>(T x, T y){ return x+y; };

Все идет нормально.

Первый вопрос: могут ли явные параметры шаблона в лямбдах шаблона быть выведены только из аргументов или можно добавить невыведенные аргументы шаблона?

Читая P0428r1, я не вижу явных ограничений, но я также не вижу примеров невыведенных аргументов шаблона.

В первом приближении я полагаю, что невыведенные аргументы шаблона допустимы, потому что я вижу, что следующий глупый код

int main()
 {   
   []<int = 0>(){ }();
 }

компилируется и запускается как с g ++ (заголовок 10.0.0), так и с clang ++ (заголовок 10.0.0).

Предположим, что невыведенные параметры шаблона разрешены, второй вопрос: как я могу вызвать лямбда-выражение шаблона, указав параметр шаблона?

На примере: учитывая следующий шаблон лямбда

auto x = []<std::size_t I>(auto t){ return std::get<I>(t); };

Есть ли какой-нибудь синтаксис для указания параметра шаблона I при вызове таких лямбда-выражений без явного именования operator()?

Я пробовал с

x<0u>(y);

но < интерпретируется как оператор отношения.

Я пробовал просто добавить template

x template <0u>(y);

но это не работает.


person max66    schedule 04.01.2020    source источник
comment
@RaymondChen - спасибо, но ... нет: не отвечает. Этот вопрос строго относится к лямбде.   -  person max66    schedule 04.01.2020
comment
Простое решение: []<std::size_t I>(std::integral_constant<std::size_t, I>, auto t) {} (std::integral_constant<std::size_t, 0>{}, ...).   -  person Evg    schedule 04.01.2020
comment
@Evg - интригующий обходной путь, но решает конкретный пример, а не общий вопрос.   -  person max66    schedule 04.01.2020
comment
@ max66: Он отвечает на ваш вопрос. Лямбды - это не какая-то магическая конструкция; они просто сокращенное обозначение того, что C ++ уже может делать. Параметры шаблона лямбды применяются к operator() лямбда, как и параметры функции auto. Следовательно, если вы хотите предоставить аргументы шаблона напрямую, вы должны использовать точно такой же синтаксис, как и для любых других operator(), где вы хотите предоставить аргументы шаблона.   -  person Nicol Bolas    schedule 04.01.2020
comment
@NicolBolas - ну ... лямбда сама по себе является синтаксическим сахаром. Я полагал, что есть другой синтаксический сахар, упрощающий это использование.   -  person max66    schedule 04.01.2020
comment
@ max66: Затем отредактируйте свой вопрос, чтобы прояснить, что вы ищете специальный синтаксис специально для лямбда-выражений, а не какой-либо синтаксис, который будет работать. Конечно, ответ будет отрицательным, потому что, опять же, лямбда - это просто структура, написанная для вас компилятором.   -  person Nicol Bolas    schedule 04.01.2020
comment
@NicolBolas - извините, но совершенно ясно, что вопрос специфичен для лямбды. Понятно в названии и ясно в теле.   -  person max66    schedule 04.01.2020
comment
Было непонятно, хотите ли вы посмотреть, добавил ли C ++ 20 новый синтаксический сахар для вызова общих лямбда-выражений.   -  person Raymond Chen    schedule 04.01.2020
comment
@RaymondChen - не только: есть еще первый вопрос: разрешен ли невыведенный параметр шаблона? Читая стандарт, я этого не понимаю.   -  person max66    schedule 04.01.2020
comment
@ max66: Читая стандарт, я этого не понимаю. Гм ... почему бы и нет? Я не понимаю, как вы могли прочитать раздел стандарта lambda-template-header и увидеть запрет на него.   -  person Nicol Bolas    schedule 04.01.2020
comment
В указанной вами документации дается пересмотренный синтаксис, разрешающий < * список-параметров-шаблонов * >, и нет установленных ограничений на то, что может входить в этот список параметров шаблона. Не уверен, что не понимаю.   -  person Raymond Chen    schedule 04.01.2020


Ответы (2)


Особых ограничений на заголовки шаблонов в лямбда-функциях нет. В конце концов, лямбды - это просто сокращение того, что вы уже могли бы сделать с любой operator() перегрузкой.

Не существует специального синтаксиса для предоставления аргументов шаблона при вызове operator() лямбда-функции. Если у вас есть параметры шаблона, которые не выводятся, вам придется использовать традиционные механизмы для предоставления этих аргументов шаблона. IE: lamb.operator()<Args>(...).

person Nicol Bolas    schedule 04.01.2020
comment
Вы имеете в виду что-то вроде x.operator()<0>()? - person L. F.; 05.01.2020
comment
@ L.F .: Да, что-то в этом роде. - person Nicol Bolas; 05.01.2020

Невыведенные аргументы лямбда-шаблона допустимы. Синтаксис для их вызова аналогичен существующей нотации функций, необходимой, когда метод вызывает перегруженный оператор того же класса; и особенно если это перегруженный шаблон оператора.

Я показываю наиболее подробную комбинацию в примере ниже, где также требуется ключевое слово template, поскольку лямбда имеет зависимое имя:

#include <tuple>

template <typename T>
void test()
{
  std::tuple tup{42, "eggs"};
  auto x = []<std::size_t I>(auto t){ return std::get<I>(t); };
  int i = x.template operator()<0>(tup);
}

int main(int argc, char *argv[])
{
  test<float>();
  return 0;
}
person user2023370    schedule 06.03.2021
comment
Истинный. Однако (текущая версия) Clang может не понравиться (например, ICE) в некоторых случаях, см. stackoverflow.com/questions/66986436/ - person Guss; 07.04.2021