#include <iostream>
#include <vector>
#include <deque>
#include <ext/pool_allocator.h>
using namespace std;

#if 1
// CASE1:不使用模版模版参数,明确指定容器的类型,比如STL库的stack实现,见下:
template <typename T,
          typename CONT = std::deque<T>>
class Stack1 {
  private:
    CONT elems;         // elements

  public:
    void push(T const&);   // push element
    void pop();            // pop element
    T top() const;         // return top element
    bool empty() const {   // return whether the stack is empty
        return elems.empty();
    }
};

int main(int argc, char const *argv[])
{

    Stack1<int, vector<int>> s;
    cout << boolalpha <<s.empty() << endl;
    return 0;
}

#elif 0
// CASE2:使用alias template的语法(c++11)传参
// 推导过程:其实E只是占位符号,会替换alias template(即using语法)中声明的原型。此处可以省略E,使用前面已出现的T。(具体参见case3)
template <typename T,
          template <typename E> class CONT = std::deque>
class Stack2
{
private:
  CONT<T> elems; // elements

public:
  void push(T const &); // push element
  void pop();           // pop element
  T top() const;        // return top element
  bool empty() const
  { // return whether the stack is empty
    return elems.empty();
  }
};

template <class E>
using Vec = vector<E, allocator<E>>;

int main(int argc, char const *argv[])
{

  Stack2<int, Vec> s;
  cout << boolalpha << s.empty() << endl;
  return 0;
}

#elif 0
// CASE3:省略E,使用之前出现过的T去做推导
template <typename T,
          template <typename> class CONT = std::deque>
class Stack3
{
private:
  CONT<T> elems; // elements

public:
  void push(T const &); // push element
  void pop();           // pop element
  T top() const;        // return top element
  bool empty() const
  { // return whether the stack is empty
    return elems.empty();
  }
};

template <class E>
using Vec = vector<E, allocator<E> >;

int main(int argc, char const *argv[])
{

  cout << "case 3" << endl;
  Stack3<int, Vec> s;
  cout << boolalpha << s.empty() << endl;
  return 0;
}

#elif 0
// CASE4
// 同理,可以不写using语法,直接在模板类中写全,此方法适用于c++98(但是需要注意两个>>在一起的时候需要加空格,不然报错)
template <typename T,
          template <typename E, typename Alloc = allocator<E> > class CONT>
class Stack4
{
private:
  CONT<T, __gnu_cxx::__pool_alloc<T>> elems; // 基于内存池的分配器

public:
  void push(T const &); // push element
  void pop();           // pop element
  T top() const;        // return top element
  bool empty() const
  { // return whether the stack is empty
    return elems.empty();
  }
};

int main(int argc, char const *argv[])
{
  cout << "case 4" << endl;
  Stack4<int, vector> s;
  cout << boolalpha << s.empty() << endl;
  return 0;
}
#elif 0
// CASE5:省略占位符E,使用之前出现过的T
// 也可以省略一个占位符号E,注意:如果有默认=出现的地方不能省略类型别名,比如“typename Alloc = allocator<T>”中的T
// 要省略T就得替换为前置出现的别名(因为省略类型之后变为了模板类),
// 比如“typename Alloc = allocator<T>”变为“template<typename M> class Alloc = alloctor”,详见case6
template <typename T,
          template <typename, typename Alloc = allocator<T>> class CONT>
class Stack5
{
private:
  CONT<T> elems; // elements

public:
  void push(T const &); // push element
  void pop();           // pop element
  T top() const;        // return top element
  bool empty() const
  { // return whether the stack is empty
    return elems.empty();
  }
};

int main(int argc, char const *argv[])
{
  cout << "case 5" << endl;
  Stack5<int, vector> s;
  cout << boolalpha << s.empty() << endl;
  return 0;
}

#elif 0
// CASE6:同理,可以省略M,使用之前的T,如case7
// CASE6\CASE7 可以通过编译,但无测试用例,太复杂。
template <typename T,
          template <typename, template <typename M> class Alloc = allocator> class CONT>
class Stack6
{
private:
  CONT<T> elems; // elements

public:
  void push(T const &); // push element
  void pop();           // pop element
  T top() const;        // return top element
  bool empty() const
  { // return whether the stack is empty
    return elems.empty();
  }
};

int main(int argc, char const *argv[])
{

  //cout << "case 6" << endl;
  // 太复杂,不建议使用,无测试成功的用例

  return 0;
}

#elif 0
// CASE7:同理,可以省略M,使用之前的T,如case7
//
template <typename T,
          template <typename, template <typename> class Alloc = allocator> class CONT>
class Stack7
{
private:
  CONT<T> elems; // elements

public:
  void push(T const &); // push element
  void pop();           // pop element
  T top() const;        // return top element
  bool empty() const
  { // return whether the stack is empty
    return elems.empty();
  }
};

int main(int argc, char const *argv[])
{

  // 太复杂,不建议使用,无测试成功的用例
  return 0;
}

#endif


备份地址: 【玩转c++模板模板参数