5.2.4. テンプレートパラメータの個数

2相テンプレートを用いることで、ホストクラスから見て同一のインタフェースを持つポリシークラスの複数の実装に、異なる個数のテンプレートパラメータを持たせることができる。以下に例を示す。

例 5.9. 異なる個数のテンプレートパラメータを持つポリシークラス

template <typename T>
class allocation_policy_new_backend
{
protected:
  void* allocate() { return ::operator new(sizeof(T)); }
  void deallocate(void* p) throw() { ::operator delete(p); }
};

struct allocation_policy_new
{
  template <typename T>
  struct bind { typedef allocation_policy_new_backend<T> type; };
};

template <typename T, class EXP>
class allocation_policy_malloc_backend
{
private:
  typedef EXP exception_type;
protected:
  void* allocate() {
    void* const p = std::malloc(sizeof(T));
    if (!p) throw exception_type();
    return p;
  }
  void deallocate(void* p) throw() { std::free(p); }
};

template <class EXP = std::bad_alloc>
struct allocation_policy_malloc
{
  template <typename T>
  struct bind { typedef allocation_policy_malloc_backend<T, EXP> type; };
};

template <typename T, class AP>
class container
  : public AP::template bind<T>::type
{
private:
  typedef typename AP::template bind<T>::type allocation_policy;
public:
  // ...
};

void foo()
{
  typedef int T;
  typedef allocation_policy_new A;
  typedef allocation_policy_malloc<> B;
  typedef allocation_policy_malloc<myexception> C;
  typedef container<T, A> C_A;
  typedef container<T, B> C_B;
  typedef container<T, C> C_C;
}

allocation_policy_newallocation_policy_mallocは2相テンプレートを用いた割り当てポリシークラスである。両者のバックエンドのクラステンプレートは互いに異なる個数のテンプレートパラメータを取るが、どちらもcontainerのポリシークラスとして機能する。

クライアントコードfooにあるように、allocation_policy_newは、そのままホストクラスcontainerにテンプレートパラメータとして渡される。一方、allocation_policy_mallocは、まずフロントエンドのクラステンプレートがfoo内で実体化され、実体化後のクラスallocation_policy_malloc<>allocation_policy_malloc<myexception>containerにテンプレートパラメータとして渡される。

一般に、2相テンプレートを用いたポリシークラスは、ポリシークラスごとに任意の個数の追加のテンプレートパラメータを設けることができる。追加のテンプレートパラメータは、ホストクラスに渡される前にクライアントコード内で束縛される。一方、すべてのポリシークラスに共通のテンプレートパラメータは、ホストクラス内で束縛される。