可以在 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
哪个编译器就在这里?
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 体内的声明也应该如此,并且应该允许问题中的定义。
就我个人而言,我认为该禁令的范围似乎定义不明确是标准中的一个缺陷。
在下面的模板定义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
哪个编译器就在这里?
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 体内的声明也应该如此,并且应该允许问题中的定义。
就我个人而言,我认为该禁令的范围似乎定义不明确是标准中的一个缺陷。