Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'typename' and alias templates

Tags:

The following code compiles using both Clang and GCC, even though Foo_t<T>::Bar doesn't have typename in front of it:

struct Foo {     using Bar = int; };  template<class...> using Foo_t = Foo;  template<class T> void f(){     Foo_t<T>::Bar b; // No typename! }  int main(){     f<int>(); } 

Should it compile?

like image 448
T.C. Avatar asked Mar 10 '15 15:03

T.C.


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.

How do I create an alias in CPP?

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 test C++?

In C++11, a type alias is a name for another already declared type, and an alias template is a name for another already declared template. Both of these types of aliases are introduced with a new using syntax.

What is a non type template parameter?

A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument. A non-type parameter can be any of the following types: An integral type. An enumeration type. A pointer or reference to a class object.


2 Answers

Introduction

Foo_t<T>::Bar might look like a dependent-name, but it isn't since the template-arguments passed to the alias-declaration are not used when determining what the qualified-id Bar is referring to.

The code is well-formed.



What does the Standard (N3337) say?

14.5.7/2 Alias templates [temp.alias]

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.

A.6 Declarations [gram.dcl]

alias-declaration:   using identifier attribute-specifier-seq_opt = type-id ; 


What is the Standard really saying?

Since there are no template-parameters in the type-id of Foo_t, the template alias-declaration is always directly equivalent to Foo, no matter what template-arguments we pass to it.

template<class... Ts> using Foo_t = Foo; //            ^--- "Foo" = type-id 

Replacing the usage of Foo_t<T> with the equivalence of the template alias-declaration leaves us with the following:

template<class T> void f(){     Foo::Bar b; // ok, nothing here depends on `T` } 
like image 78
Filip Roséen - refp Avatar answered Jan 31 '23 16:01

Filip Roséen - refp


With some more digging, this is CWG issue 1390.

The issue description is

According to 14.6.2.1 [temp.dep.type] paragraph 8, a type is dependent (among other things) if it is

a simple-template-id in which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent

This applies to alias template specializations, even if the resulting type does not depend on the template argument:

struct B { typedef int type; }; template<typename> using foo = B; template<typename T> void f() {   foo<T>::type * x;  //error: typename required } 

Is a change to the rules for cases like this warranted?

And there's a note in that issue:

Notes from the October, 2012 meeting:

CWG agreed that no typename should be required in this case. In some ways, an alias template specialization is like the current instantiation and can be known at template definition time.

The issue is still in "drafting" status, but it looks like the compiler vendors are already implementing the intended resolution.

like image 21
T.C. Avatar answered Jan 31 '23 16:01

T.C.