How to 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 will need a function that will return true if all the members of the 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 is different than other's return allDiff; } 

Inspired by what I found on the Internet, I wrote this (adapted a function that printed the contents of a tuple):

 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 true, since the compiler tells me Error C2955 'CheckTupleLoop': use of class template requires template argument list

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

+7
c ++ c ++ 11 tuples stdtuple
source share
3 answers

You can 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

The implementation for C ++ 11 from std::make_index_sequence (which is C ++ 14) can be easily found

In C ++ 17, you can even simplify a helper function:

 namespace detail { template <std::size_t ... Is, typename Tuple> bool areAllMembersDifferent(std::index_sequence<Is...>, const Tuple& left, const Tuple& right) { return (std::get<Is>(left) != std::get<Is>(right) && ...); } } 
+5
source share

You can use the following C ++ 11 compatible solution to achieve what you need:

 template <size_t N> struct CompareTuples { template<class... Args> static bool areAllMembersDifferent(const std::tuple<Args...>& left, const std::tuple<Args...>& right) { return (std::get<N>(left) != std::get<N>(right)) && CompareTuples<N-1>::areAllMembersDifferent(left, right); } }; template<> struct CompareTuples<0> { template<class... Args> static bool areAllMembersDifferent(const std::tuple<Args...>& left, const std::tuple<Args...>& right) { return (std::get<0>(left) != std::get<0>(right)); } }; template<class... Args> bool areAllMembersDifferent(const std::tuple<Args...>& left, const std::tuple<Args...>& right) { return CompareTuples<std::tuple_size<std::tuple<Args...>>::value-1>::areAllMembersDifferent(left, right); } 
+2
source share

Jarod42's answer is quite reasonable, but here are my 2 cents:

 #include <iostream> #include <tuple> #include <limits> template <size_t index> struct next_index { static const size_t value = index - 1; }; template <> struct next_index<0> { static const size_t value = 0; }; template <class Tuple, size_t index> bool is_same(const Tuple& left, const Tuple& right) { if (index != 0) return is_same<Tuple, next_index<index>::value>(left, right) and std::get<index>(left) != std::get<index>(right); return std::get<index>(left) != std::get<index>(right); } template <typename Tuple> bool areAllMembersDifferent(const Tuple& left, const Tuple& right) { return is_same<Tuple, std::tuple_size<Tuple>::value - 1>(left, right); } int main() { std::cout << areAllMembersDifferent(std::make_tuple(12, '*', 4.2f), std::make_tuple(11, '#', 4.25f)) << std::endl; std::cout << areAllMembersDifferent(std::make_tuple(12, '*', 4.2f), std::make_tuple(11, '#', 4.2f)) << std::endl; } 
0
source share

All Articles