Search code examples
c++templatesboost

boost unit test cartesian product of mpl list


Suppose I have two mpl lists, say

typedef boost::mpl::list<int, double> inner_types;
typedef boost::mpl::list<std::vector, std::set> outer_types;

I was hoping to be able, in a boost unit test, to iterate over the cartesian product of these lists and construct an object from each combination..something like the following:

BOOST_TEST_CASE_TEMPLATE(mytest, InnerType, inner_types, OuterType, outer_types) {
    OuterType<InnerType> obj;

    BOOST_CHECK(ns::foo(obj));
}

but it seems like you can only have one mpl list when using _TEMPLATE for a boost test case. Is there a way to achieve what I am intending?


Solution

  • You could use Boost MP11 similar to this to merge merge the two lists to a single Cartesian product as follows

    #include <boost/mp11.hpp>
    
    template <template <typename...> typename... F>
    using mp_list_q = boost::mp11::mp_list<boost::mp11::mp_quote<F>...>;
    
    using outer_types = mp_list_q<std::vector, std::set>;
    using inner_types = boost::mp11::mp_list<int, double>;
    
    using TypeList = boost::mp11::mp_product<boost::mp11::mp_invoke_q,  
                                             outer_types, 
                                             inner_types>;
    

    In this example TypeList corresponds to:

    boost::mp11::mp_list<std::vector<int>, std::vector<double>, std::set<int>, std::set<double>>
    

    This could then be used in a typed unit test as follows:

    BOOST_TEST_CASE_TEMPLATE_FUNCTION(foo_test, T) {
      BOOST_TEST(ns::foo(T{}) == true);
    }
    
    boost::unit_test::test_suite* init_unit_test_suite(int, char* []) {
      boost::unit_test::framework::master_test_suite().add(BOOST_TEST_CASE_TEMPLATE(foo_test, TypeList));
      return EXIT_SUCCESS;
    }
    

    Try it here!


    If for some reason you can't use Boost MP11 you could write yourself a manual solution with variadic templates to create the alias TypeList similar to the one I have written here.