Boost.PreprocessorにあるBOOST_PP_SEQ_EACH_PRODUCTのTemplate MeataProgramming版.
#っていうかBOOST_PP_SEQ_EACH_PRODUCTなんて無いし.BOOST_PP_SEQ_FOR_EACH_PRODUCTでした.っていうかこのTMP版も生成した直積を陽にシーケンスで返すんじゃなくて,各直積についてメタ関数を呼び出す形にしたほうが圧倒的に効率的ですにゃ.
#include <boost/mpl/list.hpp> #include <boost/mpl/begin_end.hpp> #include <boost/mpl/push_front.hpp> #include <boost/mpl/deref.hpp> #include <boost/mpl/next_prior.hpp> #include <boost/mpl/joint_view.hpp> template<class T, class First, class Last> struct each_product_sub2 { typedef typename boost::mpl::push_front< typename each_product_sub2< T, typename boost::mpl::next<First>::type, Last >::type, typename boost::mpl::push_front< typename boost::mpl::deref<First>::type, T >::type >::type type ; }; template<class T, class Last> struct each_product_sub2<T, Last, Last> { typedef boost::mpl::list0<> type ; }; template<class First1, class Last1, class First2, class Last2> struct each_product_sub1 { typedef typename boost::mpl::joint_view< typename each_product_sub1< typename boost::mpl::next<First1>::type, Last1, First2, Last2 >::type, typename each_product_sub2< typename boost::mpl::deref<First1>::type, First2, Last2 >::type >::type type ; }; template<class Last1, class First2, class Last2> struct each_product_sub1<Last1, Last1, First2, Last2> { typedef boost::mpl::list0<> type ; }; template<class First, class Last> struct each_product { typedef typename boost::mpl::deref<First>::type front ; typedef typename each_product< typename boost::mpl::next<First>::type, Last >::type result ; typedef typename each_product_sub1< typename boost::mpl::begin<front>::type, typename boost::mpl::end<front>::type, typename boost::mpl::begin<result>::type, typename boost::mpl::end<result>::type >::type type ; }; template<class Last> struct each_product<Last, Last> { typedef boost::mpl::list1<boost::mpl::list0<> > type ; }; //////////////////// 以上,ライブラリコード //////////////////// //////////////////// 以下,クライアントコード //////////////////// typedef boost::mpl::list3< boost::mpl::list2<char, wchar_t>, boost::mpl::list2<char, wchar_t>, boost::mpl::list2<char, wchar_t> > ll ; // 各直積を要素とするシーケンス // list< // list<wchar_t, wchar_t, wchar_t>, // list<wchar_t, wchat_t, char>, // list<wchar_t, char, wchar_t>, // list<wchar_t, char, char>, // list<char, wchar_t, wchar_t>, // list<char, wchat_t, char>, // list<char, char, wchar_t>, // list<char, char, char> // > // を作成. typedef each_product< boost::mpl::begin<ll>::type, boost::mpl::end<ll>::type >::type result ; #include <iostream> // 以下,表示用のクラステンプレート群 // // クラステンプレート + static関数は // 関数の部分特殊化をエミュレートするための常套手段 template<class First, class Last> struct mpl_sequence_printer { static void print() { std::cout << typeid(typename boost::mpl::deref<First>::type).name() << ", " ; mpl_sequence_printer<typename boost::mpl::next<First>::type, Last>::print(); } }; template<class Last> struct mpl_sequence_printer<Last, Last> { static void print() { } }; template<class First, class Last> struct mpl_sequence_of_sequence_printer { static void print() { mpl_sequence_printer< typename boost::mpl::begin< typename boost::mpl::deref<First>::type >::type, typename boost::mpl::end< typename boost::mpl::deref<First>::type >::type >::print(); std::cout << '\n'; mpl_sequence_of_sequence_printer< typename boost::mpl::next<First>::type, Last >::print(); } }; template<class Last> struct mpl_sequence_of_sequence_printer<Last, Last> { static void print() { } }; int main() { mpl_sequence_of_sequence_printer< boost::mpl::begin<result>::type, boost::mpl::end<result>::type >::print(); }
相も変わらず何の役に立つのか自分にも見当が付かないという・・・.
(´-`).。oO(いや,本当に見当が付いてないなら作らないんですが・・・)
ちなみに言うまでもないことですが,組み合わせで効いてくるのでちょっと生成元のシーケンスをでかくしただけですぐにコンパイラが悲鳴を上げます.一応,ある程度効率を考慮してlist + push_frontにしてますが・・・もっと高効率の書き方があるんだろうなぁ・・・(っていうかあるでしょう.MPLはどうもコードの効率が予測できない).
ちなみに,うちの超ヘボマシーン + VC++でも2^7 = 128の直積生成はコンパイルが通りました.・・・main関数がたった4行しかないコードのコンパイルに10分という時間が費やされましたけれどね.('Д')y ─┛~~
#そういえばTMPのコードを効率化する方法としてアンローリングかけるとかいうのをちらほら聴くなぁ.試してみたら面白いかも.アンローリングなんて言葉,行列積書いて遊んでた時以来だ・・・まさか,再度お目にかかるとはorz.