積生成 in Boost.MPL(改)

#include <boost/mpl/long.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/minus.hpp>
#include <boost/mpl/multiplies.hpp>
#include <boost/mpl/divides.hpp>
#include <boost/mpl/modulus.hpp>
#include <boost/mpl/list.hpp>
#include <boost/mpl/begin_end.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/next_prior.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/mpl/advance.hpp>
#include <boost/mpl/distance.hpp>


template<
  class SeqOfSeqFirst, class SeqOfSeqLast,
  class SeqOfIndexFirst, class SeqOfIndexLast
>
struct deref_each_product_iterator
{
  typedef
    typename boost::mpl::push_front<
      typename deref_each_product_iterator<
        typename boost::mpl::next<SeqOfSeqFirst>::type, SeqOfSeqLast,
        typename boost::mpl::next<SeqOfIndexFirst>::type, SeqOfIndexLast
      >::type,
      typename boost::mpl::at<
        typename boost::mpl::deref<SeqOfSeqFirst>::type,
        typename boost::mpl::deref<SeqOfIndexFirst>::type
      >::type
    >::type
    type
    ;
};

template<class SeqOfSeqLast, class SeqOfIndexLast>
struct deref_each_product_iterator<
  SeqOfSeqLast, SeqOfSeqLast,
  SeqOfIndexLast, SeqOfIndexLast
>
{
  typedef
    boost::mpl::list0<>
    type
    ;
};

template<class SeqOfSeq, class SeqOfSize, class SeqOfBase, class Index>
struct each_product_iterator
{
  typedef SeqOfSeq sequence_of_sequence;
  typedef SeqOfSize size_sequence;
  typedef SeqOfBase base_sequence;
  typedef Index index;
};

template<class Sequence>
struct each_product_view
{ };

template<
  class SeqOfSizeFirst, class SeqOfSizeLast,
  class SeqOfBaseFirst, class SeqOfBaseLast,
  class Index
>
struct make_index_sequence
{
  typedef
    typename boost::mpl::push_front<
      typename make_index_sequence<
        typename boost::mpl::next<SeqOfSizeFirst>::type, SeqOfSizeLast,
        typename boost::mpl::next<SeqOfBaseFirst>::type, SeqOfBaseLast,
        Index
      >::type,
      typename boost::mpl::modulus<
        typename boost::mpl::divides<
          Index,
          typename boost::mpl::deref<SeqOfBaseFirst>::type
        >::type,
        typename boost::mpl::deref<SeqOfSizeFirst>::type
      >::type
    >::type
    type
    ;
};

template<class SeqOfSizeLast, class SeqOfBaseLast, class Index>
struct make_index_sequence<
  SeqOfSizeLast, SeqOfSizeLast,
  SeqOfBaseLast, SeqOfBaseLast,
  Index
>
{
  typedef
    boost::mpl::list0<>
    type
    ;
};

template<class SeqOfSeqFirst, class SeqOfSeqLast>
struct make_size_sequence
{
  typedef
    typename boost::mpl::push_front<
      typename make_size_sequence<
        typename boost::mpl::next<SeqOfSeqFirst>::type,
        SeqOfSeqLast
      >::type,
      typename boost::mpl::size<
        typename boost::mpl::deref<SeqOfSeqFirst>::type
      >::type
    >::type
    type
    ;
};

template<class SeqOfSeqLast>
struct make_size_sequence<SeqOfSeqLast, SeqOfSeqLast>
{
  typedef
    boost::mpl::list0<>
    type
    ;
};

template<class SeqOfSizeFirst, class SeqOfSizeLast>
struct make_base_sequence_sub
{
  typedef
    typename make_base_sequence_sub<
      typename boost::mpl::next<SeqOfSizeFirst>::type,
      SeqOfSizeLast
    >::type
    tmp
    ;
  typedef
    typename boost::mpl::push_front<
      tmp,
      typename boost::mpl::multiplies<
        typename boost::mpl::front<tmp>::type,
        typename boost::mpl::deref<SeqOfSizeFirst>::type
      >::type
    >::type
    type
    ;
};

template<class SeqOfSizeLast>
struct make_base_sequence_sub<SeqOfSizeLast, SeqOfSizeLast>
{
  typedef
    boost::mpl::list<boost::mpl::long_<1> >
    type
    ;
};

template<class SeqOfSizeFirst, class SeqOfSizeLast>
struct make_base_sequence
{
  typedef
    typename boost::mpl::pop_front<
      typename make_base_sequence_sub<
        SeqOfSizeFirst,
        SeqOfSizeLast
      >::type
    >::type
    type
    ;
};

namespace boost{ namespace mpl{

template<class SeqOfSeq>
struct size<each_product_view<SeqOfSeq> >
{
  typedef
    typename make_size_sequence<
      typename boost::mpl::begin<SeqOfSeq>::type,
      typename boost::mpl::end<SeqOfSeq>::type
    >::type
    size_sequence
    ;
  typedef
    typename make_base_sequence<
      typename boost::mpl::begin<size_sequence>::type,
      typename boost::mpl::end<size_sequence>::type
    >::type
    base_sequence
    ;
  typedef
    typename boost::mpl::multiplies<
      typename boost::mpl::front<size_sequence>::type,
      typename boost::mpl::front<base_sequence>::type
    >::type
    type
    ;
};

template<class SeqOfSeq>
struct begin<each_product_view<SeqOfSeq> >
{
  typedef
    typename make_size_sequence<
      typename boost::mpl::begin<SeqOfSeq>::type,
      typename boost::mpl::end<SeqOfSeq>::type
    >::type
    size_sequence
    ;
  typedef
    typename make_base_sequence<
      typename boost::mpl::begin<size_sequence>::type,
      typename boost::mpl::end<size_sequence>::type
    >::type
    base_sequence
    ;
  typedef
    each_product_iterator<
      SeqOfSeq,
      size_sequence,
      base_sequence,
      boost::mpl::long_<0>
    >
    type
    ;
};

template<class SeqOfSeq>
struct end<each_product_view<SeqOfSeq> >
{
  typedef
    typename boost::mpl::size<each_product_view<SeqOfSeq> >::type
    size
    ;
  typedef
    typename boost::mpl::advance<
      typename boost::mpl::begin<each_product_view<SeqOfSeq> >::type,
      size
    >::type
    type
    ;
};

template<class SeqOfSeq, class SeqOfSize, class SeqOfBase, class Index>
struct next<each_product_iterator<SeqOfSeq, SeqOfSize, SeqOfBase, Index> >
{
  typedef
    each_product_iterator<
      SeqOfSeq, SeqOfSize, SeqOfBase,
      typename boost::mpl::plus<Index, boost::mpl::long_<1> >::type
    >
    type
    ;
};

template<class SeqOfSeq, class SeqOfSize, class SeqOfBase, class Index>
struct prior<each_product_iterator<SeqOfSeq, SeqOfSize, SeqOfBase, Index> >
{
  typedef
    each_product_iterator<
      SeqOfSeq, SeqOfSize, SeqOfBase,
      typename boost::mpl::plus<Index, boost::mpl::long_<-1> >::type
    >
    type
    ;
};

template<
  class SeqOfSeq, class SeqOfSize, class SeqOfBase, class Index, class N
>
struct advance<each_product_iterator<SeqOfSeq, SeqOfSize, SeqOfBase, Index>, N>
{
  typedef
    each_product_iterator<
      SeqOfSeq, SeqOfSize, SeqOfBase,
      typename boost::mpl::plus<Index, N>::type
    >
    type
    ;
};

template<
  class SeqOfSeq, class SeqOfSize, class SeqOfBase, class Index1, class Index2
>
struct distance<
  each_product_iterator<SeqOfSeq, SeqOfSize, SeqOfBase, Index1>,
  each_product_iterator<SeqOfSeq, SeqOfSize, SeqOfBase, Index2>
>
{
  typedef
    typename boost::mpl::minus<Index2, Index1>::type
    type
    ;
};

template<class SeqOfSeq, class SeqOfSize, class SeqOfBase, class Index>
struct deref<each_product_iterator<SeqOfSeq, SeqOfSize, SeqOfBase, Index> >
{
  typedef
    typename make_index_sequence<
      typename boost::mpl::begin<SeqOfSize>::type,
      typename boost::mpl::end<SeqOfSize>::type,
      typename boost::mpl::begin<SeqOfBase>::type,
      typename boost::mpl::end<SeqOfBase>::type,
      Index
    >::type
    index_sequence
    ;
  typedef
    typename deref_each_product_iterator<
      typename boost::mpl::begin<SeqOfSeq>::type,
      typename boost::mpl::end<SeqOfSeq>::type,
      typename boost::mpl::begin<index_sequence>::type,
      typename boost::mpl::end<index_sequence>::type
    >::type
    type
    ;
};

}} // namespace boost::mpl


////////////////////  以上ライブラリコード  ////////////////////
//////////////////// 以下クライアントコード ////////////////////


#include <iostream>
#include <typeinfo>

template<class First, class Last>
struct meta_sequence_printer_impl
{
  static void print()
  {
    std::cout << typeid(typename boost::mpl::deref<First>::type).name() << ", ";
    meta_sequence_printer_impl<
      typename boost::mpl::next<First>::type,
      Last
    >::print();
  }
};

template<class Last>
struct meta_sequence_printer_impl<Last, Last>
{
  static void print()
  {
    std::cout << std::endl;
  }
};

template<class Sequence>
void print_meta_sequence()
{
  meta_sequence_printer_impl<
    typename boost::mpl::begin<Sequence>::type,
    typename boost::mpl::end<Sequence>::type
  >::print();
}

template<class First, class Last>
struct print_meta_sequence_of_meta_sequence_impl
{
  static void print()
  {
    using namespace boost::mpl;

    print_meta_sequence<typename deref<First>::type>();
    print_meta_sequence_of_meta_sequence_impl<
      typename next<First>::type,
      Last
    >::print();
  }
};

template<class Last>
struct print_meta_sequence_of_meta_sequence_impl<Last, Last>
{
  static void print()
  { }
};

template<class SequenceOfSequence>
void print_meta_sequence_of_meta_sequence()
{
  using namespace boost::mpl;

  print_meta_sequence_of_meta_sequence_impl<
    typename begin<SequenceOfSequence>::type,
    typename end<SequenceOfSequence>::type
  >::print();
}

int main()
{
  using namespace boost::mpl;
  typedef
    list3<
      list2<bool, char>,
      list3<short, int, long>,
      list2<float, double>
    >
    ll
    ;

  print_meta_sequence_of_meta_sequence<each_product_view<ll> >();
}

実際に必要になる瞬間(iteratorがderefされるなど)までシーケンスを生成しないlazyな実装,要するにviewにした.
自分の環境ではVC++7.1で前のコードより3倍程度コンパイル速度が速くなった.GCCでも2倍程度速くなった.でも期待したほどの向上じゃなくて(´・ω・`)ショボーンVC++7.1,GCC3.3.1双方で試したところ,共に2^8 = 256の積生成まで耐えられる模様.
ちなみに,2^9 = 512の積生成を試してみたらコンパイラが音を上げた.特にGCCコンパイルエラーを吐くだけで12分もかかるという前代未聞の事態がw.