8

A couple of related questions for C++ standard gurus.

The incoming C++20 introduces template lambdas (P0428R2).

So instead of

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

we can specify the template parameter as follows

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

So far, so good.

First question: can explicit template parameters, in template lambdas, only be deduced from arguments, or is it possible to add non-deduced template arguments?

Reading P0428r1 I don't see any explicit limitations but, also, I don't see examples of non-deduced template arguments.

In first approximation I suppose that non-deduced template arguments are legal because I see that the following silly code

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

compiles and runs with both g++ (10.0.0 head) and clang++ (10.0.0 head).

Supposing that non-deduced template parameters are allowed, the second question is: how can I call a template lambda while providing a template parameter?

By example: given the following template lambda

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

Is there some syntax for specifying the template parameter I when invoking such lambdas without explicitly naming operator()?

I've tried with

x<0u>(y);

but the < is interpreted as a relational operator.

I've tried simply adding template

x template <0u>(y);

but it doesn't work.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
max66
  • 65,235
  • 10
  • 71
  • 111
  • @RaymondChen - thanks but... no: doesn't answer. This question is strictly related to lambda. – max66 Jan 04 '20 at 15:48
  • Simple workaround: `[](std::integral_constant, auto t) {} (std::integral_constant{}, ...)`. – Evg Jan 04 '20 at 15:49
  • @Evg - intriguing workaround but solve the specific example, not the general question. – max66 Jan 04 '20 at 15:51
  • 2
    @max66: It does answer your question. Lambdas aren't some magical construct; they're just shorthand notation for what C++ can already do. The template parameters on a lambda are applied to the `operator()` of the lambda, just like the `auto` function parameters. Therefore, if you want to provide template arguments directly, you must use exactly the same syntax as you would for any other `operator()` where you want to provide template arguments. – Nicol Bolas Jan 04 '20 at 15:51
  • @NicolBolas - well... lambda itself are syntactic sugar. I was oping there is other syntactic sugar to simplify this use. – max66 Jan 04 '20 at 15:54
  • @max66: Then edit your question to make it clear that you are looking for specialized syntax specifically for lambdas, rather than any syntax which would work. Of course, the answer would be "no", because again, a lambda is just a struct written for you by the compiler. – Nicol Bolas Jan 04 '20 at 15:54
  • @NicolBolas - sorry but is extremely clear the the question is lambda specific. Clear in the title and clear in the body. – max66 Jan 04 '20 at 15:56
  • 2
    Was not clear that you were looking to see if C++20 added **new syntactic sugar** for invoking generic lambdas. – Raymond Chen Jan 04 '20 at 15:57
  • @RaymondChen - not only: there is also the first question: it's legal a non-deduced template parameter? Reading the standard I don't understand this. – max66 Jan 04 '20 at 15:59
  • @max66: "*Reading the standard I don't understand this.*" Um... why not? I don't see how you could have read the lambda-template-header section of the standard and see a prohibition on it. – Nicol Bolas Jan 04 '20 at 16:04
  • The documented you cited gives the revised syntax as permitting a `<`*template-parameter-list*`>`, and there are no stated restrictions on what can go into that template parameter list. Not sure what's not to understand. – Raymond Chen Jan 04 '20 at 16:14

2 Answers2

7

There are no special restrictions on template headers in lambda functions. Lambdas are after all just shorthand for what you could do already with any operator() overload.

There is no special syntax for providing template arguments when invoking the operator() of a lambda function. If you have template parameters which are not deduced, you will have to use the traditional mechanisms for providing those template arguments. IE: lamb.operator()<Args>(...).

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
4

Non-deduced lambda template arguments are legal. The syntax for calling them is similar to the existing function notation required when a method calls an overloaded operator of the same class; and especially if it is an overloaded operator template.

I show the most verbose combination in the example below, where the template keyword is also required as the lambda has a dependent name:

#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;
}
user2023370
  • 10,488
  • 6
  • 50
  • 83
  • True. However, (current release of) Clang might not like (e.g ICE) it in some cases, see https://stackoverflow.com/questions/66986436/c-quickfix-to-clang-frontend-ice-when-explicitly-specifying-template-parameter – Guss Apr 07 '21 at 12:52