Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a lambda in a default template parameter considered part of the immediate context?

Is the following code well-formed C++17?

template <typename T, int = [](auto t) { decltype(t)::invalid; return 0; }(T{})>
constexpr int f(T) { return 0; }
constexpr int f(...) { return 1; }

static_assert(f(0) == 1);

clang and edg accept it, while msvc and gcc1 reject it. I can't find anything that would say that this is a hard error, but I also can't find anything that would say that this is a deduction failure.

In C++20, there is this paragraph ([temp.deduct]p9):

A lambda-expression appearing in a function type or a template parameter is not considered part of the immediate context for the purposes of template argument deduction.

which makes it clear that the lambda is not part of the immediate context. But what about C++17?


1: gcc has a bug with auto in this context, but rewriting it using explicit template parameters for the lambda gets you the same error.

like image 340
Rakete1111 Avatar asked Dec 03 '18 13:12

Rakete1111


People also ask

What is a lambda function in CPP?

In C++11 and later, a lambda expression—often called a lambda—is a convenient way of defining an anonymous function object (a closure) right at the location where it's invoked or passed as an argument to a function.

How do you pass a lambda function in C++?

Permalink. All the alternatives to passing a lambda by value actually capture a lambda's address, be it by const l-value reference, by non-const l-value reference, by universal reference, or by pointer.

What is the type of a lambda?

A type lambda lets one express a higher-kinded type directly, without a type definition. For instance, the type above defines a binary type constructor, which maps arguments X and Y to Map[Y, X] . Type parameters of type lambdas can have bounds, but they cannot carry + or - variance annotations.

Can lambda be templated?

From the various lambda improvements, template parameters for lambdas are my favorite ones. Lambdas support with C++20 template parameters, can be default-constructed and support copy-assignment, when they have no state, and can be used in unevaluated contexts.


1 Answers

It's plain ill-formed in C++17, if I gather correctly.

[expr.prim.lambda] (emphasis mine)

2 A lambda-expression shall not appear in an unevaluated operand, in a template-argument, [...]

[temp.param] (emphasis mine)

9 A default template-argument is a template-argument ([temp.arg]) specified after = in a template-parameter.

In both cases "template-argument" is the same normative term. So I think Clang and edg err by accepting the code in the OP as valid C++17.

like image 156
StoryTeller - Unslander Monica Avatar answered Sep 28 '22 11:09

StoryTeller - Unslander Monica