Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 429
dfrib Avatar asked Jun 26 '20 10:06

dfrib


Video Answer


1 Answers

(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.

like image 133
dfrib Avatar answered Oct 13 '22 12:10

dfrib