模板系列(一) 模板的模板参数

前面我们写过类似的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();

 

posted @ 2014-10-06 22:12  (@_@)ゞ  阅读(251)  评论(0编辑  收藏  举报