很难用言语形容这一点。有时我会看到这样的类:
template <typename T>
class Wrapper
{
public:
Wrapper(const T& t) : t_(t) {}
Wrapper(const Wrapper& w) : t_(w.t_) {}
private:
T t_;
}
据我所知这是合法的代码。但是,为什么允许复制构造函数接受 const Wrapper&
没有明确说明它需要 const Wrapper<T>&
。还有什么时候隐含模板类型?如果不使用类内定义,是否允许这样编写复制构造函数?
最佳答案
语言标准在14.6.1/1中明确指定:
Within the scope of class template, when the name of the template is neither qualified nor followed by <, it is equivalent to the name of the template followed by the template-parameters enclosed in <>.
在标准的后续版本中,这一点被重新措辞(通过“注入(inject)类名”的概念),但重点是这种行为在文档中明确说明。
为了回答问题的第二部分,此规则也适用于编写类外方法定义时的参数声明,但不适用于返回类型声明。例如这段代码就可以了
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 !!!
附注最后一项主张需要进一步研究。 Comeau Online 编译器认为这是一个错误,而 GCC 认为这是可以的。我稍后再回来讨论。
P.P.S。 MSVC++ 2005 中的编译器提示后一个声明并发出警告
warning C4812: obsolete declaration style: please use 'Wrapper<T>::Wrapper' instead
有趣...
关于c++ - 类里面的模板查找?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1704353/