比較のために、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の実体化では、テンプレートパラメータTがcontainerの第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 は、APAPがテンプレートパラメータを1つ持つクラステンプレートであることを意味する。クライアントコードfooはcontainerに型名ではなくクラステンプレート名を渡す。
この方法では、クライアントコードfoo内に冗長な記述はない。しかし、foo内のallocation_policy_newはクラステンプレートであって型ではないため、別名を定義することができないという問題がある。
2相テンプレートを用いた場合は、foo内のallocation_policy_newはクラステンプレートではなくクラスであるため、別名を定義できる。