jpo38 jpo38 - 16 days ago 6
C++ Question

How can I check if all members of two tuples are different?

std::tuple<...>::operator!=
returns true if at least one member of the two compared tuples is different.

I would need a function that would return true if all members of two compared tuples are different:

template <class... Args>
bool areAllMembersDifferent( const std::tuple<Args...>& left, const std::tuple<Args...>& right )
{
bool allDiff = true;

// iterate through the tuples are set allDiff to false if one member's is different than other's

return allDiff;
}


Inspired from what I found on the web, I wrote this (adapted a function that was printing the tuple content):

template <std::size_t N, std::size_t, class = make_index_sequence<N>>
struct CheckTupleLoop;

template <std::size_t N, std::size_t J, std::size_t... Is>
struct CheckTupleLoop<N, J, index_sequence<Is...>> {
template <class Tup>
int operator()(bool& allDiff, const Tup &left,const Tup &right) {
if ( std::get<J>(left) == std::get<J>(right) )
allDiff = false;
return 0;
}
};

template <class... Args>
bool areAllMembersDifferent( const std::tuple<Args...>& left, const std::tuple<Args...>& right )
{
bool allDiff = true;
CheckTupleLoop<sizeof...(Args)>{}(allDiff,left,right);
return allDiff;
}


But this is obviously not correct as the compiler reports me
Error C2955 'CheckTupleLoop': use of class template requires template argument list


Any kind of implementation of
bool areAllMembersDifferent
in C++11 would be acceptable (using or not my first attempt approach).

Answer

You may use the following:

namespace detail
{

template <std::size_t ... Is, typename Tuple>
bool areAllMembersDifferent(std::index_sequence<Is...>,
                            const Tuple& left,
                            const Tuple& right)
{
    bool res = true;

    const int dummy[] = {0, (res &= std::get<Is>(left) != std::get<Is>(right), 0)...};
    static_cast<void>(dummy); // Avoid warning for unused variable
    return res;
}

}

template <typename Tuple>
bool areAllMembersDifferent(const Tuple&left, const Tuple& right)
{
    return detail::areAllMembersDifferent(
        std::make_index_sequence<std::tuple_size<Tuple>::value>(), left, right);
}

Demo

Implementation for c++11 of std::make_index_sequence (which is C++14) can be found easily