Not sure if title is descriptive, but what I would like is this:
input:
- list of templates(in my case containers) taking 1 (required, can be more optional) type arguments
- list of types
output:
"cartesian product" where each template in first set is instantiated with every type in second set.
example:
template_list<std::vector, std::set> x type_list<int, double> =>
type_list<std::vector<int>, std::vector<double>, std::set<int>, std::set<double>>
I found this question, but that is about a case when elements of both sets are types.
How to create the Cartesian product of a type list?
I presume that what I want is impossible without macros, but it may be possible that I am missing something.
CodePudding user response:
You could use std::tuple
s. Especially std::tuple_cat
is nice for this.
Example:
#include <iostream>
#include <set>
#include <tuple>
#include <type_traits>
#include <vector>
template <template <class...> class... C>
struct template_list {};
template <template <class...> class C, class... Ts>
auto toc(const std::tuple<Ts...>&) {
return std::tuple<C<Ts>...>{};
}
template <template <class...> class... C, class... Ts>
auto operator*(template_list<C...>, const std::tuple<Ts...>& tup) {
return std::tuple_cat(toc<C>(tup)...);
}
int main() {
template_list<std::vector, std::set> templ;
std::tuple<int, double, float> typel;
auto res = templ * typel;
static_assert(
std::is_same_v<decltype(res),
std::tuple<std::vector<int>, std::vector<double>,
std::vector<float>, std::set<int>,
std::set<double>, std::set<float>>>);
}
CodePudding user response:
As in my answer on he linked question, with Boost.Mp11, this is a short one-liner (as always):
using templates = mp_list<mp_quote<std::vector>, mp_quote<std::set>>;
using types = mp_list<int, double>;
using result = mp_product<
mp_invoke_q,
templates, types>;
static_assert(std::same_as<
result,
mp_list<std::vector<int>,
std::vector<double>,
std::set<int>,
std::set<double>
>>);
Demo.
Note that you need templates
as mp_list<mp_quote<C1>, mp_quote<C2>>
instead of template_list<C1, C2>
, since metaprogramming is lot easier if everything is a type. But that's not a huge burden.