【问题标题】:Difference between adding and omitting template parameter for class name inside constructor在构造函数中为类名添加和省略模板参数之间的区别
【发布时间】:2016-11-12 14:46:01
【问题描述】:
我想知道两者之间是否有本质区别:
template <typename T>
class foo{
foo<T>(){};
};
template<typename T>
class foo{
foo(){};
};
两者似乎都有效,但我不明白两者之间的区别。第一个让我很困惑,我不明白在这里的作用是什么。
【问题讨论】:
标签:
c++
templates
constructor
typename
injected-class-name
【解决方案1】:
根据injected-class-name的规则,它们完全是一回事。
$14.6.1/1 Locally declared names [temp.local]:
与普通(非模板)类一样,类模板有一个
注入类名称(子句 [类])。注入的类名可以是
用作模板名称或类型名称。当它与一个
模板参数列表,作为模板的模板参数
模板参数,或作为最终标识符
友元类模板声明的详细类型说明符,它
指类模板本身。否则等价于
模板名称后跟类的模板参数
.
中包含的模板
所以foo 和foo<T> 在这里指的是同一个东西。更具体地说,
第一个让我很困惑,我不明白在这里的作用是什么。
您正在使用注入类名称foo 及其模板参数T(即foo<T>),它引用模板类本身。
【解决方案2】:
请注意,从 C++20 开始,较长的形式不再有效,您必须使用依赖于 injected-class-name 的较短形式。
见[diff.cpp17]#class-2:
simple-template-id 不再作为构造函数或析构函数的 declarator-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)。