GCC is wrong. tmp_t
declares a new template (an alias template to be precise). And this new template is distinct from any other template.
[temp.alias] (emphasis mine)
1 A template-declaration in which the declaration is an
alias-declaration declares the identifier to be an alias template. An
alias template is a name for a family of types. The name of the
alias template is a template-name.
The text in bold means that tmp_t
refers to the new alias template, it does not refer to whatever the alias' specializations may be defined as. As such S<tmp_t>
and S<Tmp>
are two specializations with different arguments.
To contrast, there are special rules that make alias template specializations stand in for the exact thing they alias
2 When a template-id refers to the specialization of an alias
template, it is equivalent to the associated type obtained by
substitution of its template-arguments for the template-parameters in
the type-id of the alias template.
So the while template-id tmp_t<foo>
means exactly the same thing as Tmp<foo>
, tmp_t
itself (without arguments) is not a template-id (it does not name a specialization). Instead it names the template, a different entity.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…