How do I compare tuples for equivalent types disregarding type order?

By counting types of both tuples, you may do something like:

template <typename T, typename Tuple>
struct type_counter;

template <typename T, typename ... Ts>
struct type_counter<T, std::tuple<Ts...>> :
    std::integral_constant<std::size_t, (... + std::is_same<T, Ts>::value)> {};

template <typename Tuple1, typename Tuple2, std::size_t... Is>
constexpr bool equivalent_types(const Tuple1&, const Tuple2&, std::index_sequence<Is...>)
{
    return (...
            && (type_counter<std::tuple_element_t<Is, Tuple1>, Tuple1>::value
               == type_counter<std::tuple_element_t<Is, Tuple1>, Tuple2>::value));
}

template <typename Tuple1, typename Tuple2>
constexpr bool equivalent_types(const Tuple1& t1, const Tuple2& t2)
{
    constexpr auto s1 = std::tuple_size<Tuple1>::value;
    constexpr auto s2 = std::tuple_size<Tuple2>::value;

    return s1 == s2
      && equivalent_types(t1, t2, std::make_index_sequence<std::min(s1, s2)>());
}

Demo C++17
Demo C++14

I use c++17 for folding expression but it can be rewritten as constexpr function easily.


With Hana (packaged with recent Boost versions), we can convert each tuple type into a map from types to the number of times they occur and then comparing those maps for equality:

template <typename T, typename U>
bool equivalent_types(T t, U u) {
    namespace hana = boost::hana;
    auto f = [](auto m, auto&& e) {
        auto k = hana::decltype_(&e);
        return hana::insert(hana::erase_key(m, k),
            hana::make_pair(k, hana::find(m, k).value_or(0) + 1));
    };
    return hana::fold(t, hana::make_map(), f) == hana::fold(u, hana::make_map(), f);
}

Example.

Note that &e as the argument to hana::decltype_ is necessary to ensure that e.g. int and int& are treated as different types (ditto with passing e by universal reference).