Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alias of a template. Who's right?

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?

like image 750
Hrisip Avatar asked Nov 09 '19 18:11

Hrisip


People also ask

What is an alias template?

Alias templates are a way to give a name to a family of types. Template parameters can be types, non-types, and templates themselves.

What is meant by alias in c++?

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.

What is an alias template?

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

What is an alias type in C++?

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)

What is the difference between type alias declaration and typedef declaration?

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.


1 Answers

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.

like image 178
StoryTeller - Unslander Monica Avatar answered Oct 18 '22 12:10

StoryTeller - Unslander Monica