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

  • A+

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.


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.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: