模板元编程之类模板(一)

TechNomad / 2023-06-18 / 原文

一、类模板Stack的实现

#include <iostream>
#include <vector>

template <typename T>
class Stack {
private:
    std::vector<T> elems; //存储元素的容器

public:
    void push(T const&); //压入元素
    void pop(); //弹出元素
    T top() const; //返回栈顶元素
    bool empty() const {
        return elems.empty();
    }
};

template <typename T>
void Stack<T>::push(T const& elem) {
    elems.push_back(elem); //把elems的拷贝附加到末尾
}

template <typename T>
void Stack<T>::pop() {
    if (elems.empty) {
        throw std::out_of_range("Stack<>::pop():empty stack");
    }

    elems.pop_back();
}

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

    return elems.back(); //返回最后一个元素的拷贝
}

二、类模板的声明

类模板的声明和函数模板的声明很类似

template <typename T> 
class Stack {
    ...
};

另外,可以再次使用关键字class来代替typename:

template <class T>
class Stack {
    ...
};

在类模板的内部,T可以像其他任何类型一样,用于声明成员变量和成员函数,在下面的示例中,T被用于声明vector的元素类型,声明push()是一个接收常量T引用为唯一实参的成员函数,声明top是返回类型为T的成员函数:

template <typename T>
class Stack {
private:
    std::vector<T> elems; //存储元素的容器

public:
    void push(T const&); //压入元素
    void pop(); //弹出元素
    T top() const; //返回栈顶元素
};

这个类的类型是Stack<T>,其中T是类模板参数,因为,在声明中需要使用该类的类型时,必须使用Stack<T>。例如,如果你要声明自己实现的拷贝构造函数和赋值运算符,那应该如下述示例:

template <typename T>
class Stack {
    ...
    Stack(Stack<T> const&); //拷贝构造函数
    Stack<T>& operator=(Stack<T> const&); //赋值运算符
};

但是,但使用类名而不是类的类型时,就应该只用Stack,比如,当指定类的名称,类的构造函数,析构函数时,就应该使用Stack。