テンプレートテンプレートパラメータ
#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>