将类型声明为类型模板参数的模板参数的一部分是否合法?
Is it legal to declare a type as part of the template-argument for a type template-parameter?
以下所有标准参考均指N4659: March 2017 post-Kona working draft/C++17 DIS。
以下代码片段成功编译了所有标准版本(1),适用于 Clang 和 GCC。
template<typename Tag>
struct Tagged {};
Tagged<struct Tag1> t1;
Tagged<struct Tag2> t2;
A template-argument for a template-parameter which is a type shall be a type-id.
和[temp.arg.type]/2包含注释
[ Note: A template type argument may be an incomplete type ([basic.types]). — end note ]
因此,我将访问 template-argument 和 type-id 的语法,以了解前者是否可能还允许声明一个(不完整的)class 类型;换句话说,如果 class-head 可以用作 template-argument 的一部分;来自 [class]/1:
class-head:
class-key attribute-specifier-seq_opt class-head-name class-virt-specifier_opt base-clause_opt
class-key attribute-specifier-seq_opt base-clause_opt
...
class-key:
class
struct
union
然而,对于 a template-argument, a type-id, an id-expression and eventually an identifier 的语法,深入探索并不会导致接受 class-head 的语法。
我可能在寻找错误的语法 (class-head) 来解释上面的片段是否真的合法。
问题
- 将类型声明为类型 模板参数 的 模板参数 的一部分是否合法?如果是这样,标准的哪一部分(例如,C++17)对此进行了管理?
(1) 请注意,如果我们放置 Tagged<struct Tag1> t1;
例如在函数范围内,代码在 C++03 中格式错误,因为 本地类型 在当时不允许作为类型模板参数的模板参数。
(看来 OP(我自己)最初并没有深入到 type-id 语法兔子洞)
Is it legal to declare a type as part of the template-argument for a type template-parameter?
是的,这是合法的。
If so, which part of the standard (say, C++17) governs this?
一个class-key和identifier文法序列,比如说struct Tag1
,就是a valid elaborated-type-specifier,
elaborated-type-specifier:
class-key attribute-specifier-seq_opt nested-name-specifier_opt identifier
...
type-specifier:
elaborated-type-specifier
...
的有效单个条目
type-specifier-seq:
type-specifier attribute-specifier-seq_opt
这又是 a valid type-id,
type-id:
type-specifier-seq abstract-declarator_opt
...
并且如 OP 中所述,type-id,根据 [temp.arg.type]/1,是有效的 template-argument 对于类型 模板参数 ;
A template-argument for a template-parameter which is a type shall be a type-id.
因此,片段
template<typename Tag>
struct Tagged {};
Tagged<struct Tag1> t1;
Tagged<struct Tag2> t2;
格式正确。
以下所有标准参考均指N4659: March 2017 post-Kona working draft/C++17 DIS。
以下代码片段成功编译了所有标准版本(1),适用于 Clang 和 GCC。
template<typename Tag>
struct Tagged {};
Tagged<struct Tag1> t1;
Tagged<struct Tag2> t2;
A template-argument for a template-parameter which is a type shall be a type-id.
和[temp.arg.type]/2包含注释
[ Note: A template type argument may be an incomplete type ([basic.types]). — end note ]
因此,我将访问 template-argument 和 type-id 的语法,以了解前者是否可能还允许声明一个(不完整的)class 类型;换句话说,如果 class-head 可以用作 template-argument 的一部分;来自 [class]/1:
class-head: class-key attribute-specifier-seq_opt class-head-name class-virt-specifier_opt base-clause_opt class-key attribute-specifier-seq_opt base-clause_opt ... class-key: class struct union
然而,对于 a template-argument, a type-id, an id-expression and eventually an identifier 的语法,深入探索并不会导致接受 class-head 的语法。
我可能在寻找错误的语法 (class-head) 来解释上面的片段是否真的合法。
问题
- 将类型声明为类型 模板参数 的 模板参数 的一部分是否合法?如果是这样,标准的哪一部分(例如,C++17)对此进行了管理?
(1) 请注意,如果我们放置 Tagged<struct Tag1> t1;
例如在函数范围内,代码在 C++03 中格式错误,因为 本地类型 在当时不允许作为类型模板参数的模板参数。
(看来 OP(我自己)最初并没有深入到 type-id 语法兔子洞)
Is it legal to declare a type as part of the template-argument for a type template-parameter?
是的,这是合法的。
If so, which part of the standard (say, C++17) governs this?
一个class-key和identifier文法序列,比如说struct Tag1
,就是a valid elaborated-type-specifier,
elaborated-type-specifier: class-key attribute-specifier-seq_opt nested-name-specifier_opt identifier ...
的有效单个条目type-specifier: elaborated-type-specifier ...
type-specifier-seq: type-specifier attribute-specifier-seq_opt
这又是 a valid type-id,
type-id: type-specifier-seq abstract-declarator_opt ...
并且如 OP 中所述,type-id,根据 [temp.arg.type]/1,是有效的 template-argument 对于类型 模板参数 ;
A template-argument for a template-parameter which is a type shall be a type-id.
因此,片段
template<typename Tag> struct Tagged {}; Tagged<struct Tag1> t1; Tagged<struct Tag2> t2;
格式正确。