5.2.3. 2相テンプレートを用いない場合との比較

比較のために、2相テンプレートを用いないコードを示す。

例 5.7. 2相テンプレートを用いないポリシークラス (1)

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

template <typename T, class AP>
class container
  : public AP
{
private:
  typedef AP allocation_policy;
  using allocation_policy::allocate;
  using allocation_policy::deallocate;
public:
  // ...
};

void foo()
{
  typedef int T;
  container<T, allocation_policy_new<T> > C;
  // ...
}

2相テンプレートを用いた場合よりも、ポリシークラスとホストクラスの記述は短い。しかし、クライアントコードfoo内のcontainerの実体化では、テンプレートパラメータTcontainerの第1パラメータとallocation_policy_newの第1パラメータの2箇所に記述されていて、冗長である。また冗長なだけでなく危険である: この2箇所に誤って異なる型を与えてしまったら、おそらく正常に動作しないだろう。2相テンプレートを用いた場合はこのような問題は発生しない。

この冗長性を排除するだけならば、2相テンプレートを用いずとも、ポリシークラスを受け取るテンプレートパラメータにテンプレートを用いることでも解決できる。以下に例を示す。

例 5.8. 2相テンプレートを用いないポリシークラス (2)

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

template <typename T, template <typename> class AP>
class container
  : public AP<T>
{
private:
  typedef AP<T> allocation_policy;
  using allocation_policy::allocate;
  using allocation_policy::deallocate;
public:
  // ...
};

void foo()
{
  typedef int T;
  container<T, allocation_policy_new> C;
  // ...
}

ホストクラスcontainerの第2テンプレートパラメータに関する記述template <typename> class APは、APがテンプレートパラメータを1つ持つクラステンプレートであることを意味する。クライアントコードfoocontainerに型名ではなくクラステンプレート名を渡す。

この方法では、クライアントコードfoo内に冗長な記述はない。しかし、foo内のallocation_policy_newはクラステンプレートであって型ではないため、別名を定義することができないという問題がある。

2相テンプレートを用いた場合は、foo内のallocation_policy_newはクラステンプレートではなくクラスであるため、別名を定義できる。