Difference between adding and omitting template parameter for class name inside constructor

187 Views Asked by At

I want to know if there is essentially a difference between:

template <typename T> 
class foo{
  foo<T>(){};
};

template<typename T>
class foo{
  foo(){};
};

Both seem to work, but I don't understand the difference between the two. The first one is confusing me, I don't understand what's the role of the < T > here.

2

There are 2 best solutions below

0
On BEST ANSWER

According to the rule of injected-class-name, they're exalctly the same thing.

$14.6.1/1 Locally declared names [temp.local]:

Like normal (non-template) classes, class templates have an injected-class-name (Clause [class]). The injected-class-name can be used as a template-name or a type-name. When it is used with a template-argument-list, as a template-argument for a template template-parameter, or as the final identifier in the elaborated-type-specifier of a friend class template declaration, it refers to the class template itself. Otherwise, it is equivalent to the template-name followed by the template-parameters of the class template enclosed in <>.

So foo and foo<T> refer to the same thing here. More specifically,

The first one is confusing me, I don't understand what's the role of the < T > here.

You're using the inject-class-name foo with its template parameter T (i.e. foo<T>), which refers to the template class itself.

0
On

Note that since C++20, the longer form is no longer valid and you have to use the shorter form that relies on injected-class-name.

See [diff.cpp17]#class-2:

a simple-template-id is no longer valid as the declarator-id of a constructor or destructor

With the following example in the spec:

template<class T>
struct A {
  A<T>();           // error: simple-template-id not allowed for constructor
  A(int);           // OK, injected-class-name used
  ~A<T>();          // error: simple-template-id not allowed for destructor
};

And indeed GCC trunk version rejects code using the longer form (while Clang 11 and GCC 10.2 still accepts it).