diff --git a/dune/stuff/common/tuple.hh b/dune/stuff/common/tuple.hh index c173787416a1451ce65f31531fbedc77a039d29e..e9469440d1fa366b7a172b56b75aa149ad0e50d7 100644 --- a/dune/stuff/common/tuple.hh +++ b/dune/stuff/common/tuple.hh @@ -4,6 +4,14 @@ #include <dune/common/tuples.hh> #include <dune/common/typetraits.hh> +#include <boost/mpl/if.hpp> +#include <boost/mpl/deref.hpp> +#include <boost/mpl/begin.hpp> +#include <boost/mpl/end.hpp> +#include <boost/mpl/next.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/type_traits.hpp> + #define TMAX(t_, no_) (Dune::tuple_size<t_>::value >= (no_ + 1) ? no_ : 0) #define TELE(t_, s_, no_) typename Dune::tuple_element<TMAX(t_, no_), t_>::type::s_ @@ -214,6 +222,80 @@ struct FullTuple : public Dune::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9> } }; +// reduced from +// http://stackoverflow.com/questions/1492204/is-it-possible-to-generate-types-with-all-combinations-of-template-arguments +namespace TupleProduct { +using boost::is_same; +using boost::mpl::begin; +using boost::mpl::end; +using boost::mpl::next; +using boost::mpl::if_; +using boost::mpl::deref; + +unsigned int total_recursions = 0; + +struct end_of_recursion_tag +{ + static void Run() + { + std::cout << "end of " << total_recursions << " recursions\n"; + } +}; + +template <class UTypes, // Forward Sequence, e.g. boost::mpl::vector + class VTypes, // Forward Sequence, e.g. boost::mpl::vector + class TestFunc // class type that has a nested templated run() member function + > +struct Combine +{ + // forward declaration + template <class UIterator, class VIterator> + struct Generate; + + // this class implements recursion body + template <class UIterator, class VIterator> + struct Next + { + // u_begin is not necessary ;) + // it would be cheaper not to pre-declare all of them since we force evaluation + // however this dramatically increase the readability + typedef typename begin<VTypes>::type v_begin; + + typedef typename end<UTypes>::type u_end; + typedef typename end<VTypes>::type v_end; + + typedef typename next<UIterator>::type u_next; + typedef typename next<VIterator>::type v_next; + + typedef + typename if_<boost::is_same<v_next, v_end>, + typename if_<boost::is_same<u_next, u_end>, end_of_recursion_tag, Generate<u_next, v_begin>>::type, + Generate<UIterator, v_next>>::type type; + }; + + // this class run test on generated types in thos round and go to next*/ + template <class UIterator = typename begin<UTypes>::type, class VIterator = typename begin<VTypes>::type> + struct Generate + { + // generate <<next>> target type + typedef typename Next<UIterator, VIterator>::type next_type; + + static void Run() + { + // increment recursion counter + ++total_recursions; + + // test on the generated types of this round of recursion + TestFunc::template run<typename deref<UIterator>::type, typename deref<VIterator>::type>(); + + // go to the next round of recursion + next_type::Run(); + } + }; +}; + +} // namespace TupleProduct + } // namespace Common } // namespace Stuff } // namespace Dune diff --git a/dune/stuff/test/common_tuple.cc b/dune/stuff/test/common_tuple.cc index c9c9c6799303170566fce20cd619e5511969065e..15d50af27f830b69d00957f642609193d1c64767 100644 --- a/dune/stuff/test/common_tuple.cc +++ b/dune/stuff/test/common_tuple.cc @@ -20,11 +20,29 @@ public: typedef Dune::tuple<A, B, B> MyTuple; +struct print_value +{ + template <class U, class V> + static void run() + { + std::cout << "(" << U::value << "," << V::value << ")" << std::endl; + } +}; + TEST(TypeTransform, All) { typedef TUPLE_TYPEDEFS_2_TUPLE(MyTuple, MyFancyType) MySubTupleType; } +TEST(Product, All) +{ + using namespace DSC::TupleProduct; + typedef boost::mpl::vector<Int<1>, Int<2>> u_types; + typedef boost::mpl::vector<Int<3>, Int<4>> v_types; + typedef Combine<u_types, v_types, print_value>::Generate<> base_generator_type; + base_generator_type::Run(); +} + int main(int argc, char** argv) { testing::InitGoogleTest(&argc, argv);