Is it legal to declare a type as part of the template-argument for a type template-parameter?

半城伤御伤魂 提交于 2020-08-04 04:29:21

问题


All standard references below refers to N4659: March 2017 post-Kona working draft/C++17 DIS.


The following snippet successfully compiles for all standard versions(1) for both Clang and GCC.

template<typename Tag>
struct Tagged {};

Tagged<struct Tag1> t1;
Tagged<struct Tag2> t2;

[temp.arg.type]/1 requires that

A template-argument for a template-parameter which is a type shall be a type-id.

and [temp.arg.type]/2 contains the note

[ Note: A template type argument may be an incomplete type ([basic.types]).  — end note ]

Thus, I would visit the grammar for a template-argument as well as a type-id to understand whether the former may also allow declaring an (incomplete) class type; in other words, if a class-head may be used as part of a template-argument; from [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

However, going down the rabbit hole for the grammar of a template-argument, a type-id, an id-expression and eventually an identifier does not lead to, afaict, a grammar accepting a class-head.

I may be looking for the wrong grammar (class-head) to explain whether the snippet above is actually legal or not.

Question

  • 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?

(1) Note that if we place Tagged<struct Tag1> t1; e.g. within the scope of a function, the code is ill-formed in C++03, as local types were not allowed, back then, as template arguments for type template parameters.


回答1:


(It seems the OP (myself) did not initially go deep enough down the type-id grammar rabbit hole)


Is it legal to declare a type as part of the template-argument for a type template-parameter?

Yes, this is legal.

If so, which part of the standard (say, C++17) governs this?

A class-key and identifier grammar sequence, say struct Tag1, is a valid elaborated-type-specifier,

elaborated-type-specifier:
    class-key attribute-specifier-seq_opt nested-name-specifier_opt identifier
    ...

which in turn is a valid type-specifier,

type-specifier:
    elaborated-type-specifier
    ...

which is turn is a valid single entry of a type-specifier-seq,

type-specifier-seq:
    type-specifier attribute-specifier-seq_opt

which in turn is a valid type-id,

type-id:
    type-specifier-seq abstract-declarator_opt
    ...

and as was noted in the OP, a type-id, as per [temp.arg.type]/1, is a valid template-argument for a type template-parameter;

A template-argument for a template-parameter which is a type shall be a type-id.

Thus, the snippet

template<typename Tag>
struct Tagged {};

Tagged<struct Tag1> t1;
Tagged<struct Tag2> t2;

is well-formed.



来源:https://stackoverflow.com/questions/62593093/is-it-legal-to-declare-a-type-as-part-of-the-template-argument-for-a-type-templa

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!