在构造函数中为 class 名称添加和省略模板参数的区别

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

我想知道两者之间是否存在本质区别:

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

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

两者似乎都有效,但我不明白两者之间的区别。第一个把我搞糊涂了,我不明白这里的是什么作用

根据injected-class-name的规则,它们是完全一样的。

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

所以foofoo<T>在这里指的是同一件事。更具体地说,

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

您正在使用注入-class-名称 foo 及其模板参数 T(即 foo<T>),它指的是模板 class本身。

请注意,自 C++20 起,较长的形式不再有效,您必须使用依赖于 injected-class-name 的较短形式.

[diff.cpp17]#class-2:

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

使用规范中的以下示例:

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
};

确实是 GCC trunk 版本 rejects code using the longer form (while Clang 11 and GCC 10.2 still accepts it).