c++templatesboostc++17boost-mpl

Cartesian product of multiple templates


I have a few classes:

template <int,char>
class Foo{};
template <int,char>
class Bar{};

And I want to get all combinations with a few arguments, like this:

// {1, 2}, {'a', 'b'}
using CartesianProduct = mp_list<Foo<1,'a'>, Foo<1,'b'>,...,Bar<2,'b'>>;

I can change template parameters to types and use std::integral_constant, if it cannot be done with numeric constants.

I found a similar question, but it's far more difficult. Creating all template permutations with MPL. I assume, there is a better and easier solution for my case.


Solution

  • Finally, I figured it out by myself.

    using namespace boost::mp11;
    
    template <typename C1, typename C2>
    struct Foo{};
    
    template <typename C1, typename C2>
    struct Bar{};
    
    template <template <typename...> typename... F>
    using mp_list_q = mp_list<mp_quote<F>...>;
    
    using TypeList = mp_product<mp_invoke_q, 
        mp_list_q<Foo, Bar>, 
        mp_list_c<int, 1, 2>, 
        mp_list_c<char, 'a', 'b'>>;
    

    Result:

    boost::mp11::mp_list<
    Foo<std::integral_constant<int, 1>, std::integral_constant<char, (char)97> >,
    Foo<std::integral_constant<int, 1>, std::integral_constant<char, (char)98> >,
    Foo<std::integral_constant<int, 2>, std::integral_constant<char, (char)97> >,
    Foo<std::integral_constant<int, 2>, std::integral_constant<char, (char)98> >,
    Bar<std::integral_constant<int, 1>, std::integral_constant<char, (char)97> >,
    Bar<std::integral_constant<int, 1>, std::integral_constant<char, (char)98> >,
    Bar<std::integral_constant<int, 2>, std::integral_constant<char, (char)97> >,
    Bar<std::integral_constant<int, 2>, std::integral_constant<char, (char)98> > >
    

    It uses std::integral_constant for arguments, but it's simple and short. Try it here

    UPD: And I found how to use integers itselfs!

    template <int, char>
    struct Foo{};
    
    template <int, char>
    struct Bar{};
    
    template <template <auto...> typename F>
    struct mp_quote_c
    {
        template <typename... C>
        using fn = F<C::value...>;
    };
    
    template <template <auto...> typename... F>
    using mp_list_qc = mp_list<mp_quote_c<F>...>;
    
    using TypeList = mp_product<mp_invoke_q,
        mp_list_qc<Foo, Bar>,
        mp_list_c<int, 1, 2>, 
        mp_list_c<char, 'a', 'b'>>;
    

    Result:

    boost::mp11::mp_list<
    Foo<1, (char)97>, Foo<1, (char)98>, Foo<2, (char)97>, Foo<2, (char)98>,
    Bar<1, (char)97>, Bar<1, (char)98>, Bar<2, (char)97>, Bar<2, (char)98> >
    

    Try it here!

    UPD2: Only clang can compile this code. It seems like there is a bug in msvc and gcc, because clang can build this code even with -pedantic-errors

    UPD3: Now gcc also can compile it