Boost.MPLのapply
メタ関数のように、プレースホルダーにしたテンプレート引数をあとで置き換える実装のサンプルです。
テンプレートテンプレートパラメータを使った部分特殊化で実装します。
#include <iostream> #include <vector> #include <list> template <class T> class my_vector { std::vector<T> data_; public: void push_back(const T& x) { data_.push_back(x); } void print() { for (const T& x : data_) { std::cout << x << std::endl; } } }; template <class T> class my_list { std::list<T> data_; public: void push_back(const T& x) { data_.push_back(x); } void print() { for (const T& x : data_) { std::cout << x << std::endl; } } }; struct _ {}; template <class> struct arg; template <template <class> class T> struct arg<T<_>> { template <class Arg> using apply = T<Arg>; }; template <class Container> class X { // 2. プレースホルダーになってるテンプレート引数をあとで置き換える typename arg<Container>::template apply<int> cont; public: void push() { cont.push_back(3); } void print() { cont.print(); } }; int main() { X<my_vector<_>> x1; // 1. テンプレート引数をプレースホルダーにして x1.push(); x1.print(); X<my_list<_>> x2; x2.push(); x2.print(); }
出力:
3 3
テンプレートテンプレートパラメータはテンプレート引数を埋めないと型になれないので扱いが難しいです。なので、テンプレートテンプレートパラメータを直接使うのではなく、プレースホルダーを使うか、Boost.Graphのadjacency_list
のようにポリシー方式で渡すかにするのがよいです。