テンプレートテンプレートパラメータ

#include <iostream>
#include <vector>

template <typename T>
class VecSample
{
	std::vector<T> m_vec;

public:
	void push (const T& elem) { m_vec.push_back(elem); }
};

int main()
{
	VecSample<int> vSample;
	vSample.push(10);
	
	return 0;
}

上記プログラムがあったとします。これは、コンパイルOKです。
で、VecSampleクラスのメンバであるvector型を、テンプレートにしたいと思ったとします。
直観的に書いてみると、

#include <iostream>
#include <vector>

template <typename T, class C>
class CSample
{
	C<T> m_container;
	
public:
	void push (const T& elem) { m_container.push_back(elem); }
};

int main()
{
	CSample<int, std::vector> cSample;
	cSample.push(10);
	
	return 0;
}

残念ながら、これはコンパイルできません。
じゃ、どうするかというと、テンプレートテンプレートパラメータを使う必要があります。

#include <iostream>
#include <vector>

template <typename T,
          template <typename ELEM> class C>
class CSample
{
	C<T> m_container;

public:
	void push (const T& elem) { m_container.push_back(elem); }
};

int main()
{
	CSample<int, std::vector> cSample;
	cSample.push(10);
	
	return 0;
}
template <typename T, template <typename ELEM> class C>

の2番目のテンプレートパラメータをテンプレートテンプレートパラメータといい、
これは「Cは型ELEMをテンプレートパラメータとするクラステンプレート」と表現している。
ちなみに、「class C」の部分を、「typename C」とするのはダメです。
Cはクラスを定義するのに使われているので、「class C」とする必要があります。

しかし、これでコンパイルすると、

CSample<int, std::vector> cSample;

の部分で、コンパイルエラーとなる。
なぜなら、vectorのテンプレート定義が、

template <class T, class Allocator = allocator<T> >
class vector;

となっているので、2つ目のパラメータのアロケータを定義しないといけません。
つまり、以下のようにするとコンパイルOKとなります。

#include <iostream>
#include <vector>

template <typename T,
          template <typename ELEM,
                    typename ALLOC = std::allocator<ELEM> >
                    class C>
class CSample
{
	C<T> m_container;

public:
	void push (const T& elem) { m_container.push_back(elem); }
};

int main()
{
	CSample<int, std::vector> cSample;
	cSample.push(10);
	
	return 0;
}

また、ALLOCというパラメータ名は使用していないので、以下のように省略できる。

typename = std::allocator<ELEM>