模板系列(一) 模板的模板参数
前面我们写过类似的Stack:
template <typename T, typename Alloc = std::vector<T> > class Stack { public: void push(const T &); void pop(); T top() const; bool empty() const; private: Alloc _cont; };
那么我们使用的时候需要这样:
Stack<string, list<string> > st;
我们看到,string这个类型参数出现了两次,那么可不可以消除呢?
显然我们的目的是只指定容器的类型,而不包括元素的类型,这就需要借助模板的模板参数,来帮助我们写出一下代码:
Stack<string, list> st;
这里我们需要定义模板参数的第二项为模板:
template <typename T, template <typename ELEM> class Alloc = std::vector> class Stack;
我们写出一份完整的实现:
1 template <typename T, 2 template <typename ELEM> 3 class Alloc = std::vector> 4 class Stack 5 { 6 public: 7 void push(const T &s); 8 void pop(); 9 T top() const 10 { return _cont.back(); } 11 12 bool empty() const 13 { return _cont.empty(); } 14 private: 15 Alloc<T> _cont; 16 }; 17 18 template <typename T, template <typename> class Alloc> 19 void Stack<T, Alloc>::push(const T &s) 20 { 21 _cont.push_back(s); 22 } 23 24 template <typename T, template <typename> class Alloc> 25 void Stack<T, Alloc>::pop() 26 { 27 _cont.pop_back(); 28 }
然而该段代码仍然会编译错误,这是因为无论是vector还是list都有两个模板参数,于是无法与Alloc这个参数匹配。
我们将模板修改为:
template <typename T, template <typename ELEM, typename Alloc = std::allocator<ELEM> > class Container = std::vector> class Stack;
完整的实现为:
1 template <typename T, 2 template <typename ELEM, typename Alloc = std::allocator<ELEM> > 3 class Container = std::vector> 4 class Stack 5 { 6 public: 7 void push(const T &s); 8 void pop(); 9 T top() const 10 { return _cont.back(); } 11 12 bool empty() const 13 { return _cont.empty(); } 14 private: 15 Container<T> _cont; 16 }; 17 18 template <typename T, template <typename, typename> class Container> 19 void Stack<T, Alloc>::push(const T &s) 20 { 21 _cont.push_back(s); 22 } 23 24 template <typename T, template <typename, typename> class Container> 25 void Stack<T, Alloc>::pop() 26 { 27 _cont.pop_back(); 28 }
测试代码为:
Stack<string, list> st; st.push("foo"); st.pop();