Cartesian product (redux)
In this blog post we looked at programs to compute Cartesian Products. One algorithm (given here in OCaml) if you recall is
let prod l r = let g acc a = let f acc x = (a, x) :: acc in List.fold_left f acc r in List.fold_left g [] l |> List.rev
In that earlier post I translated the above program into C++. This time I'm doing the same straightforward translation but using the Boost.MPL library to compute such products at compile time. It looks like this:
#include <boost/mpl/pair.hpp> #include <boost/mpl/vector.hpp> #include <boost/mpl/push_front.hpp> #include <boost/mpl/fold.hpp> #include <boost/mpl/reverse.hpp> #include <boost/mpl/placeholders.hpp> using namespace boost::mpl::placeholders; template <class L, class R> struct product { struct g { template <class AccT, class A> struct apply { typedef typename boost::mpl::fold < R, AccT , boost::mpl::push_front<_1, boost::mpl::pair<A, _2> > >::type type; }; }; typedef typename boost::mpl::reverse < typename boost::mpl::fold < L, boost::mpl::vector<>, g>::type>::type type; };The translation proceeds almost mechanically! Does it work though? You betcha! Here's a test we can convince ourselves with:
#include <boost/mpl/equal.hpp> #include <boost/mpl/for_each.hpp> #include <boost/mpl/int.hpp> #include <iostream> using namespace boost::mpl; typedef vector<int_<1>, int_<2> > A; typedef vector<int_<3>, int_<4>, int_<5> > B; typedef product <A, B>::type result; BOOST_MPL_ASSERT(( equal< result , vector< pair<int_<1>, int_<3> > , pair<int_<1>, int_<4> > , pair<int_<1>, int_<5> > , pair<int_<2>, int_<3> > , pair<int_<2>, int_<4> > , pair<int_<2>, int_<5> > > > )); struct print_class_name { template <typename T> void operator()( T t ) const { std::cout << typeid(t).name() << " "; } }; int main () { boost::mpl::for_each<result>(print_class_name()); return 0; }The takeaway is, learning yourself some functional programming is a great way to improve your template meta-programming fu! (That of course should come as no surprise... )