The following code seems reasonable, but doesn't work on two major compilers
#include <type_traits>
template<template<class> class Tmp>
struct S{
template<class T>
using tmp_t = Tmp<T>;
static_assert(std::is_same_v< S<tmp_t>, S<Tmp> >,
"Not same?? How come?");
};
template<class> struct Dummy{};
template struct S<Dummy>;
gcc starting with 7.1 compiles alright ( https://godbolt.org/z/DjAcgP )
clang ( https://godbolt.org/z/ewBbZJ )
and
msvc ( https://godbolt.org/z/6ZmQwj )
fail to do so
Is this code standard conformant?
Alias templates are a way to give a name to a family of types. Template parameters can be types, non-types, and templates themselves.
You can use an alias declaration to declare a name to use as a synonym for a previously declared type. (This mechanism is also referred to informally as a type alias). You can also use this mechanism to create an alias template, which can be useful for custom allocators.
Alias template is a name that refers to a family of types. Alias declarations are declarations with the following syntax: the name that is introduced by this declaration, which becomes either a type name (1) or a template name (2) abstract declarator or any other valid type-id (which may introduce a new type, as noted in type-id ).
Type alias is a name that refers to a previously defined type (similar to typedef ). Alias template is a name that refers to a family of types. Alias declarations are declarations with the following syntax: the name that is introduced by this declaration, which becomes either a type name (1) or a template name (2)
It does not introduce a new type and it cannot change the meaning of an existing type name. There is no difference between a type alias declaration and typedef declaration. This declaration may appear in block scope, class scope, or namespace scope.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With