一、主模板
#include <vector>
#include <stdexcept>
template <typename T>
class Stack {
private:
// 元素
std::vector<T> elems;
public:
// push 元素
void push(T const&);
// pop 元素
void pop();
// 传回最顶端元素
T top() const;
// stack 是否为空
bool empty() const {
return elems.empty();
}
};
template <typename T>
void Stack<T>::push (T const& elem) {
// 追加(附于尾)
elems.push_back(elem);
}
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<>::top: empty stack");
}
// 传回最后一个元素的拷贝
return elems.back();
}
二、针对string的特化后的模板
你可以针对某些特殊的 template arguments, 对一个 class template 进行 「特化」 。 class templates 的特化与 function template 的重载类似,使你得以针对某些特定类型进行程序代码优化, 或修正某个特定类型在 class template 实例(instantiation) 中的错误行为 。 然而如果你对一个 class template 进行特化,就必须特化其所有成员函数。虽然你可以特化某个单独的成员函数,但一旦这么做,也就不再是特化整个 class template。
欲特化某个class template,必须以template<> 开头声明此一class,后面跟着你希望的特化结果。特化类型(specialized type)将作为template arguments 并在class名称之后直接写明:
template<>
class Stack<std::string> {
...
};
对特化体(specializations)而言,每个成员函数都必须像常规的(一般的)成员函数那样定义, 每一个 T 出现处都必须更换为特化类型(specialized type):
void Stack<std::string>::push (std::string const& elem) {
elems.push_back(elem); // 将传入的 elem 附加于尾
}
下面是一个针对 std::string 类型而特化的 Stack<> 的完整范例:
#include <deque>
#include <string>
#include <stdexcept>
#include "stack1.hpp"
template<>
class Stack<std::string> {
private:
// 元素
std::deque<std::string> elems;
public:
// push 元素
void push(std::string const&);
// pop 元素
void pop();
// 传回 stack 最顶端元素
std::string top() const;
// stack 是否为空
bool empty() const {
return elems.empty();
}
};
void Stack<std::string>::push (std::string const& elem) {
// 追加元素
elems.push_back(elem);
}
void Stack<std::string>::pop () {
if (elems.empty()) {
throw std::out_of_range("Stack<std::string>::pop(): empty stack");
}
// 移除最后一个元素
elems.pop_back();
}
std::string Stack<std::string>::top () const {
if (elems.empty()) {
throw std::out_of_range("Stack<std::string>::top(): empty stack");
}
// 传回最后一个元素的拷贝
return elems.back();
}
此例之中,我们在stack内部改用deque代替vector来管理元素。这么做并没有特别的好处,但它示范「一个特化实作码可以和其primary template(主模板。注:最原始的那一份定义)有相当程度的差异」。