Home > Software engineering >  Cartesian product of list of templates and list of types to instantiate them with
Cartesian product of list of templates and list of types to instantiate them with

Time:02-13

Not sure if title is descriptive, but what I would like is this:

input:

  1. list of templates(in my case containers) taking 1 (required, can be more optional) type arguments
  2. 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::tuples. 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>>>);
}

Demo

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.

  • Related