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

c++, c++14, comparison, stdtuple, tuples

Solution

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.

Problem

I'm looking for a way to compare two tuples to see if they contain the same types. The order of the types does not matter. As long as there is a one to one mapping between the types of the two tuples, I will consider them equivalent. Here is a small test I have set up. I am having trouble implementing `equivalent_types()`: ``` #include <iostream> #include <utility> #include <tuple> #include <functional> template <typename T, typename U> bool equivalent_types(T t, U u){ return (std::tuple_size<T>::value == std::tuple_size<U>::value); //&& same types regardless of order } int main() { //these tuples have the same size and hold the same types. //regardless of the type order, I consider them equivalent. std::tuple<int,float,char,std::string> a; std::tuple<std::string,char,int,float> b; std::cout << equivalent_types(a,b) << '\n'; //should be true std::cout << equivalent_types(b,a) << '\n'; //should be true //examples that do not work: //missing a type (not enough types) std::tuple<std::string,char,int> c; //duplicate type (too many types) std::tuple<std::string,char,int,float,float> d; //wrong type std::tuple<bool,char,int,float> e; std::cout << equivalent_types(a,c) << '\n'; //should be false std::cout << equivalent_types(a,d) << '\n'; //should be false std::cout << equivalent_types(a,e) << '\n'; //should be false } ```

Original source