可以在 C++ 的模板参数列表中定义类型吗?

Can a type be defined inside a template parameter list in C++?

在下面的模板定义struct B中,lambda被用作非类型模板参数的默认值,并且在lambda的主体中定义了一些类型A

template <auto = []{ struct A{}; }>
struct B {};

Clang 和 MSVC 对此定义没有问题,但 GCC 抱怨:

error: definition of 'struct<lambda()>::A' inside template parameter list

演示:https://gcc.godbolt.org/z/f1dxGbPvs

哪个编译器就在这里?

[temp.param]/2 说:

Types shall not be defined in a template-parameter declaration.

照这样写,GCC 拒绝此代码是正确的:此禁止不限于类型参数的 type-id,而是适用于模板参数声明中的任何位置.包括嵌套在 lambda 中。

这句话是由于DR 1380 (N3481), which reveals it was considered already implied by what now I am guessing to be [dcl.fct]/17而添加的:

Types shall not be defined in return or parameter types.

然而,这似乎只适用于声明的参数类型,而不适用于 initializer-clause.

另一方面,人们也可能将其解读为在模板参数中禁止 lambda 本身。毕竟,lambda 表达式隐式定义了一个 class 类型 ([expr.prim.lambda.closure]/1).

在第三个方面,我们还有 [expr.prim.lambda.closure]/2,其中指出:

The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression.

这里的相关作用域好像是命名空间作用域。这意味着应该将 lambda 视为其类型是在模板参数列表之外声明的。但是,lambda 体内的声明也应该如此,并且应该允许问题中的定义。

就我个人而言,我认为该禁令的范围似乎定义不明确是标准中的一个缺陷。