3.5 缺省模板实参
对于类模板,你还可以为模板参数定义缺省值;这些值就被称为缺省模板实参;而且,它们还可以引用之前的模板参数。例如,在类Stack<>中,你可以把用于管理元素的容器定义为第2个模板参数,并且使用std::vector<>作为它的缺省值:
//basics/stack3.hpp
#include <vector>
#include <stdexcept>
template <typename T, typename CONT = std::vector<T> >
class Stack {
private:
CONT elems; // 包含元素的容器
public:
void push(T const&); // 压入元素
void pop(); // 弹出元素
T top() const; // 返回栈顶元素
bool empty() const { // 返回栈是否为空
return elems.empty();
}
};
template <typename T, typename CONT>
void Stack<T,CONT>::push (T const& elem)
{
elems.push_back(elem); // 把传入实参elem附加到末端
}
template <typename T, typename CONT>
void Stack<T,CONT>::pop ()
{
if (elems.empty()) {
throw std::out_of_range("Stack<>::pop(): empty stack");
}
elems.pop_back(); // 删除末端元素
}
template <typename T, typename CONT>
T Stack<T,CONT>::top () const
{
if (elems.empty()) {
throw std::out_of_range("Stack<>::top(): empty stack");
}
return elems.back(); // 返回末端元素的拷贝
}
可以看到:我们的类模板含有两个模板参数,因此每个成员函数的定义都必须具有这两个参数:
template <typename T,typename CONT>
void Stack<T,CONT>::push(T const& elem)
{
elems.push_back(elem); //附加传入实参elem的拷贝
}
你仍然可以像前面例子一样使用这个栈(stack);就是说,如果你只传递第一个类型实参给这个类模板,那么将会利用vector来管理stack的元素:
template<typename T,typename CONT = std::vector<T> >
class Stack {
private:
CONT elems; //包含元素的容器
...
};
另外,当在程序中声明Stack对象的时候,你还可以指定容器的类型:
//basics/stack3test.cpp
#include <iostream>
#include <deque>
#include <cstdlib>
#include "stack3.hpp"
int main()
{
try {
// int栈:
Stack<int> intStack;
// double栈,它使用std::deque来管理元素
Stack<double,std::deque<double> > dblStack;
// 使用int栈
intStack.push(7);
std::cout << intStack.top() << std::endl;
intStack.pop();
// 使用double栈
dblStack.push(42.42);
std::cout << dblStack.top() << std::endl;
dblStack.pop();
dblStack.pop();
}
catch (std::exception const& ex) {
std::cerr << "Exception: " << ex.what() << std::endl;
return EXIT_FAILURE; // 退出程序,且有ERROR标记
}
}
使用
Stack<double,std::deque<double> >
你可以声明一个“元素类型为double,并且使用std::deque<>在内部管理元素”的栈。