它由 14.6.1/1 中的语言标准明确指定:
在类模板的范围内,当模板名既没有限定也没有后跟<时,相当于模板名后跟<>中的模板参数。
这在标准的更高版本中被重新措辞(通过“注入的类名”的概念),但关键是这种行为在文档中明确说明。
要回答您问题的第二部分,此规则在编写类外方法定义时也适用于参数声明,但不适用于返回类型声明。比如这段代码就OK
template <typename T> struct S {
S foo(S);
};
template <typename T> S<T> S<T>::foo(S s) {
/* whatever */
}
但是您不能<T>
从方法定义中的返回类型中删除该位。(并且您不能<T>
从方法的限定名称中删除。)
至于具体的构造函数:你应该使用<T>
类的全名(带),但你不应该<T>
在构造函数本身的名称中使用。因此,在您的情况下,课外定义的最短形式是
template <typename T> Wrapper<T>::Wrapper(const Wrapper& w) : t_(w.t_)
{
}
请注意,<T>
即使您想要,也不能将位添加到构造函数名称中
template <typename T> Wrapper<T>::Wrapper<T>(const Wrapper& w)
^ ERROR !!!
PS 最后一个说法需要进一步研究。Comeau Online 编译器认为这是一个错误,而 GCC 认为它是 OK 的。我稍后会回到它。
PPS MSVC++ 2005 中的编译器抱怨后一种声明并带有警告
warning C4812: obsolete declaration style: please use 'Wrapper<T>::Wrapper' instead
有趣的...