在构造函数中添加和省略类名的模板参数之间的区别

时间:2016-11-12 14:46:02

标签: c++ templates constructor typename injected-class-name

我想知道:

之间是否存在本质区别
template <typename T> 
class foo{
  foo<T>(){};
};

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

两者似乎都有效,但我不明白两者之间的区别。第一个让我感到困惑,我不明白&lt;&lt;&lt; T>这里。

2 个答案:

答案 0 :(得分:2)

根据injected-class-name的规则,他们在同样的事情上也是如此。

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

  

与普通(非模板)类一样,类模板也有   inject-class-name(Clause [class])。注入类名可以   用作模板名称或类型名称。与它一起使用时   template-argument-list,作为模板的模板参数   template-parameter,或者作为最终标识符   它是一个友元类模板声明的详细说明类型说明符   指的是类模板本身。否则,它相当于   template-name后跟类的模板参数   括在&lt;&gt;。

中的模板

所以foofoo<T>在这里引用相同的内容。更具体地说,

  

第一个让我感到困惑,我不明白&lt;&lt; T>这里。

您正在使用inject-name-name foo及其模板参数T(即foo<T>),它指的是模板类本身。

答案 1 :(得分:1)

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

[diff.cpp17]#class-2

<块引用>

简单模板 ID 不再作为构造函数或析构函数的声明符 ID 有效

使用规范中的以下示例:

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 主干版本 rejects code using the longer form(而 Clang 11 和 GCC 10.2 still accepts it)。