Nico Schlömer
Nico Schlömer

Reputation: 58781

Loop over template types

I have a function with two template arguments, one for a vector data type (int, float, double, etc.) and one for an integer type (int, int16_t, uint32_t, etc.):

template <typename T, typename I>
void
add(std::vector<T> array, std::vector<I> idx) {
  // ...
}

For tests, I would now like to loop over every possible combination of data/integer types, e.g.,

// pseudo code
for I in [int, int16_t, int32_t, ...] {
    for T in [float, double, int, int16_t, ...] {
        // create arguments a, b
        add<T, I>(a, b);
    }
}

Is it possible to loop over types at all? How?

Upvotes: 2

Views: 206

Answers (2)

user4442671
user4442671

Reputation:

If you have boost at hand then boost::hana is definitely the way to go. However, it's not very hard to reimplement that feature by hand if you have to:

#include <iostream>

template<typename... T>
struct iterator {
  template<typename CB_T>
  static void iterate(CB_T const& ) {}
};

template<typename first, typename... rest>
struct iterator<first, rest...> {
  template<typename CB_T>
  static void iterate(CB_T const& cb) {
    cb(first());
    iterator<rest...>::iterate(cb);
  }
};

int main() {
  iterator<int, float>::iterate([](auto const & v_1){
    using v_1_t = decltype(v_1);
    iterator<char, double>::iterate([&](auto const & v_2){
      using v_2_t = decltype(v_2);
      std::cout << typeid(v_1_t).name() << " vs " << typeid(v_2_t).name() << "\n";
    });
  });
  return 0;
}

Upvotes: 1

linuxfever
linuxfever

Reputation: 3823

There may be simpler ways to do this, but I would use the boost hana library, as follows:

#include <boost/hana/for_each.hpp>
#include <boost/hana/tuple.hpp>
#include <vector>
#include <iostream>
#include <boost/type_index.hpp>

namespace hana = boost::hana;

// for example's sake, just print the type
template <typename T, typename I>
void add(std::vector<T> array, std::vector<I> idx) {

    using namespace boost::typeindex;
    std::cout << type_id<T>().pretty_name() << " - " << type_id<I>().pretty_name() << std::endl;
}

int main() {

    auto types1 = hana::tuple_t<int, int16_t, int32_t>;
    auto types2 = hana::tuple_t<float, double, int, int16_t>;

    hana::for_each(types1, [types2](auto t1) {

        hana::for_each(types2, [t1](auto t2) {

            using t1_type = typename decltype(t1)::type;
            using t2_type = typename decltype(t2)::type;

            add<t1_type, t2_type>({}, {});
        });
    });
}

Upvotes: 1

Related Questions