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.
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> >
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