方法定义中的C ++模板参数

时间:2012-09-09 14:13:41

标签: c++ templates

是否需要使用该参数声明具有模板参数的类中的所有方法声明?编译器似乎需要类似下面的内容

// Queue.h
template <class ItemType>
class Queue
{
    Queue();
    ItemType dequeue();
    int count();
    /* ... other methods ... */
};
// Queue.cpp
template <class ItemType>
Queue<ItemType>::Queue()
{ /*...*/ }
template <class ItemType>
int Queue<ItemType>::count()
{/*...*/}
template <class ItemType>
ItemType Queue<ItemType>::dequeue()
{/* ... */}

来自Java / C#,这似乎有点多余 - 我觉得我应该能够更像这样定义方法:

int Queue::count() 

签名不引用ItemType,因此我们可以省略它。

Queue::ItemType Queue::dequeue() 

签名引用ItemType,但编译器知道我们正在讨论模板参数,因为我们使用Queue::

来限定标识符

3 个答案:

答案 0 :(得分:5)

是的,您需要提供模板参数。请注意,虽然它可能看起来多余,但事实并非如此。 C ++模板是Java泛型的一个更强大的工具,它们允许进行特化。这意味着使用基本模板Queue可能有多个实现匹配不同的模板参数并具有不同的定义。或者,您可以使用单个Queue模板,其中包含一些针对某些功能的特化。这两种情况要求您同时提供template参数列表和类模板参数:

// Just member specialization
template <typename T>
struct X {
   void foo() { std::cout << "generic\n"; }
};
// specialize just this member for `int`
template <>
void X<int>::foo() { std::cout << "int\n"; }
int main() {
   X<double> xd; xd.foo();  // generic
   X<int>    xi; xi.foo();  // int
}

// Class template specialization
template <typename T>
struct X {
   void foo();
}
template <typename T>
struct X<T*> {
   void bar();
}
template <typename T>
void X<T>::foo() { std::cout << "generic\n"; }
template <typename T>
void X<T*>::bar() { std::cout << "ptr\n"; }
int main() {
   X<int > xi; xi.foo();       // generic
   X<int*> xp; xp.bar();       // ptr
}

答案 1 :(得分:2)

是的,他们这样做,并且它不是多余的,因为Queue不是没有模板参数的类型。但是,您可以在类模板声明中提供函数定义:

template <class ItemType>
class Queue
{
    Queue();
    ItemType dequeue() { /* implementation */}
    int count() { /* implementation */ }
    /* ... other methods ... */
};

请记住这个

Queue<int> q;
int i = q.dequeue();

相当于

Queue<int> q;
int i = Queue<int>::dequeue(&q);

换句话说,需要完整类型来限定函数名称,即使函数本身没有引用模板参数(尽管在这种情况下,返回类型需要模板参数)。

答案 2 :(得分:1)

是。

当成员函数,成员类,成员枚举,静态数据成员或成员时 类模板的模板是在类模板定义之外定义的,成员定义是 定义为模板定义,其中模板参数是类模板的参数。该 成员定义中使用的模板参数的名称可能与模板不同 类模板定义中使用的参数名称。