In the following definition of template struct B, a lambda is used as a default value of a non-type template argument, and in the body of the lambda some type A is defined:
template <auto = []{ struct A{}; }>
struct B {};
Clang and MSVC are fine with this definition, but GCC complains:
error: definition of '
struct<lambda()>::A' inside template parameter list
Demo: https://gcc.godbolt.org/z/f1dxGbPvs
Which compiler is right here?
CodePudding user response:
[temp.param]/2 says:
Types shall not be defined in a template-parameter declaration.
Taking this as written, GCC is correct to reject this code: this prohibition is not constrained to type-id of a type parameter, but applies to anywhere within template parameter declaration. Including nested within a lambda.
On the other hand, one might also read it as prohibiting lambdas themselves in template parameters. After all, a lambda expression implicitly defines a class type ([expr.prim.lambda.closure]/1).
On the third hand, we also have [expr.prim.lambda.closure]/2, which states:
The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression.
The relevant scope here seems to be the namespace scope. This would imply the lambda should be treated as if its type were declared outside the template parameter list. But then, so should be declarations inside the body of the lambda, and the definition in the question should be allowed.
Personally, I consider it a defect in the standard that the scope of this prohibition seems so ill-defined.
