一个专注音视频领域的小圈子

在之前的类模板中,只在类声明时用了 typename 指定模板参数类型,之后的成员函数复用模板参数类型。

但实际上,类成员也可以是模板,嵌套类和成员函数都可以作为模板。

如下代码所示:

template<typename T>
class Stack {
private:
    std::deque<T> elems;

public:
    void push(T const &elem);

    void pop();

    T top() const;

    bool empty() const {
        return elems.empty();
    }

    template<typename T2>
    Stack<T> &operator=(Stack<T2> const &);
};

template<typename T>
void Stack<T>::push(const T &elem) {
    elems.push_back(elem);
}

template<typename T>
void Stack<T>::pop() {
    if (!elems.empty()) {
        elems.pop_back();
    }
}

template<typename T>
T Stack<T>::top() const {
    if (!elems.empty()) {
        return elems.back();
    }
    throw std::out_of_range("Stack::top(); empty Stack");
}

template<typename T>
template<typename T2>
Stack<T> &Stack<T>::operator=(const Stack<T2> &op2) {
    if ((void *) this == (void *) &op2) {
        return *this;
    }

    Stack<T2> tmp(op2);
    elems.clear();
    while (!tmp.empty()) {
        elems.push_front(tmp.top());
        tmp.pop();
    }
    return *this;
}

以上类和之前定义的 Stack 类略有差别,主要是自定义了赋值运算符,可以将两个不同类型的 Stack 容器内容进行转换。

在自定义的赋值运算符中,除了类模板声明的类型参数 T 之外,还多了一个 T2 的类型参数,此时的成员函数也成了一个模板函数。

在类模板中,成员函数的模板参数可以和类的模板参数不同,但在定义中必须添加两个模板参数列表。

其中,第一个为类的模板参数,第二个为成员函数的。

template<typename T>
class MyClass {
public:
    template<typename T2> 
    void func(T2 t2);
};

template<typename T>
template<typename T2>
void MyClass<T>::func(T2 t2) {

}

同样的,类模板的成员模板也只有在调用时才会实例化,否则不会。

成员模板既可以在类模板中,也可以在普通类中。

class MyClass2{
public:
    template<typename T>
    void func(T t);
};

template<typename T>
void MyClass2::func(T t) {

}

原创文章,转载请注明来源:    C++ 模板系列小结04-类模板中的成员模板