课堂上的模板查找?

时间:2009-11-09 22:26:05

标签: c++ templates lookup

很难说清楚这一点。有时我会看到这样的课程:

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>&。什么时候隐含的模板类型?如果不使用类内定义,是否允许以这种方式编写复制构造函数?

4 个答案:

答案 0 :(得分:3)

基本上,在类模板定义中,您可以使用 template-name 将模板定义为 template-id的完整参数化版本的简写

答案 1 :(得分:3)

它由14.6.1 / 1中的语言标准明确指定:

  

在类模板的范围内,   当模板的名称是   既不合格也不跟随&lt;   它相当于的名称   模板后面跟着   模板参数包含在&lt;&gt;。

这是在标准的后续版本中重新措辞(通过“注入类名”的概念),但重点是文档中明确说明了这种行为。

要回答问题的第二部分,此规则在编写类外方法定义时也适用于参数声明,但它不适用于返回类型声明。例如,此代码正常

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

P.S。最后一项声明需要进一步研究。 Comeau Online编译器认为这是一个错误,而GCC认为它是可以的。我稍后会回来。

P.P.S。 MSVC ++ 2005中的编译器抱怨后一个声明带有警告

warning C4812: obsolete declaration style: please use 'Wrapper<T>::Wrapper' instead

...有趣

答案 2 :(得分:0)

在这样的模板化类中,使用类的名称与使用Wrapper<T>相同。

答案 3 :(得分:0)

不,你不得不写下课:

template <typename T>
Wrapper<T>::Wrapper<T>(const Wrapper<T>& w) : t(w.t) {}

但在课堂上,Wrapper代表“当前班级”。

编辑:这是安德鲁和他调查编译器拒绝构造函数的原因:

template <typename T>
class Foo {
public:
    Foo() {}
    Foo(const Foo& f);
};

template <typename T>
Foo<T>::Foo<T>(const Foo<T>& f) { }

int main(int argc, char** argv)
{
    Foo<int> f;
    Foo<int> g(f); // make sure the template is instantiated
}