operator==,!=,<,<=,>,>=,<=>(std::tuple)

From cppreference.com
< cpp‎ | utility‎ | tuple
 
 
Utilities library
General utilities
Date and time
Function objects
Formatting library (C++20)
(C++11)
Relational operators (deprecated in C++20)
Integer comparison functions
(C++20)(C++20)(C++20)   
(C++20)
Swap and type operations
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
Common vocabulary types
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)
Elementary string conversions
(C++17)
(C++17)
 
std::tuple
Member functions
Non-member functions
operator==operator!=operator<operator<=operator>operator>=operator<=>
(until C++20)(until C++20)(until C++20)(until C++20)(until C++20)(C++20)
Deduction guides(C++17)
Helper classes
 
Defined in header <tuple>
(1)
template< class... TTypes, class... UTypes >

bool operator==( const std::tuple<TTypes...>& lhs,

                 const std::tuple<UTypes...>& rhs );
(since C++11)
(until C++14)
template< class... TTypes, class... UTypes >

constexpr bool operator==( const std::tuple<TTypes...>& lhs,

                           const std::tuple<UTypes...>& rhs );
(since C++14)
(2)
template< class... TTypes, class... UTypes >

bool operator!=( const std::tuple<TTypes...>& lhs,

                 const std::tuple<UTypes...>& rhs );
(since C++11)
(until C++14)
template< class... TTypes, class... UTypes >

constexpr bool operator!=( const std::tuple<TTypes...>& lhs,

                           const std::tuple<UTypes...>& rhs );
(since C++14)
(until C++20)
(3)
template< class... TTypes, class... UTypes >

bool operator<( const std::tuple<TTypes...>& lhs,

                const std::tuple<UTypes...>& rhs );
(since C++11)
(until C++14)
template< class... TTypes, class... UTypes >

constexpr bool operator<( const std::tuple<TTypes...>& lhs,

                          const std::tuple<UTypes...>& rhs );
(since C++14)
(until C++20)
(4)
template< class... TTypes, class... UTypes >

bool operator<=( const std::tuple<TTypes...>& lhs,

                 const std::tuple<UTypes...>& rhs );
(since C++11)
(until C++14)
template< class... TTypes, class... UTypes >

constexpr bool operator<=( const std::tuple<TTypes...>& lhs,

                           const std::tuple<UTypes...>& rhs );
(since C++14)
(until C++20)
(5)
template< class... TTypes, class... UTypes >

bool operator>( const std::tuple<TTypes...>& lhs,

                const std::tuple<UTypes...>& rhs );
(since C++11)
(until C++14)
template< class... TTypes, class... UTypes >

constexpr bool operator>( const std::tuple<TTypes...>& lhs,

                          const std::tuple<UTypes...>& rhs );
(since C++14)
(until C++20)
(6)
template< class... TTypes, class... UTypes >

bool operator>=( const std::tuple<TTypes...>& lhs,

                 const std::tuple<UTypes...>& rhs );
(since C++11)
(until C++14)
template< class... TTypes, class... UTypes >

constexpr bool operator>=( const std::tuple<TTypes...>& lhs,

                           const std::tuple<UTypes...>& rhs );
(since C++14)
(until C++20)
template< class... TTypes, class... UTypes >

constexpr /* see below */ operator<=>( const std::tuple<TTypes...>& lhs,

                                       const std::tuple<UTypes...>& rhs );
(7) (since C++20)
1-2) Compares every element of the tuple lhs with the corresponding element of the tuple rhs.
3-6) Compares lhs and rhs lexicographically by operator<, that is, compares the first elements, if they are equivalent, compares the second elements, if those are equivalent, compares the third elements, and so on.

For non-empty tuples, (3) is equivalent to

if (std::get<0>(lhs) < std::get<0>(rhs)) return true;
if (std::get<0>(rhs) < std::get<0>(lhs)) return false;
if (std::get<1>(lhs) < std::get<1>(rhs)) return true;
if (std::get<1>(rhs) < std::get<1>(lhs)) return false;
...
return std::get<N - 1>(lhs) < std::get<N - 1>(rhs);
7) Compares lhs and rhs lexicographically by synthesized three-way comparison (see below), that is, compares the first elements, if they are equivalent, compares the second elements, if those are equivalent, compares the third elements, and so on.

The return type is the common comparison category type of results of synthesized three-way comparison on every pair of element in lhs and rhs. For empty tuples, the return type is std::strong_ordering.
For non-empty tuples, (7) is equivalent to

if (auto c = synth_three_way(std::get<0>(lhs), std::get<0>(rhs)); c != 0) return c;
if (auto c = synth_three_way(std::get<1>(lhs), std::get<1>(rhs)); c != 0) return c;
...
return synth_three_way(std::get<N - 1>(lhs), std::get<N - 1>(rhs));
where synth_three_way is an exposition-only function object performing synthesized three-way comparison.

sizeof...(TTypes) and sizeof...(UTypes) must be equal, otherwise the program is ill-formed or for operator<=>, the operator function does not participate in overload resolution (since C++20). N in above code is equal to both.

All comparison operators are short-circuited; they do not access tuple elements beyond what is necessary to determine the result of the comparison.

The <, <=, >, >=, and != operators are synthesized from operator<=> and operator== respectively.

(since C++20)

Synthesized three-way comparison

Given two object types T and U, a const T lvalue t as left hand operand, a const U lvalue u is right hand operand, synthesized three-way comparison is defined as:

  • if std::three_way_comparable_with<T, U> is satisfied, equivalent to t <=> u;
  • otherwise, if comparing a const T lvalue with a const U lvalue in both orders are well-formed and the result types satisfies boolean-testable, equivalent to
t < u ? std::weak_ordering::less :
u < t ? std::weak_ordering::greater :
        std::weak_ordering::equivalent
  • otherwise, synthesized three-way comparison is not defined, which makes operator<=> do not participate in overload resolution.

The behavior of operator<=> is undefined if three_way_comparable_with or boolean-testable is satisfied but not modeled.

(since C++20)

Parameters

lhs, rhs - tuples to compare

Return value

1) true if std::get<i>(lhs) == std::get<i>(rhs) for all i in [0, sizeof...(Types)), otherwise false. For two empty tuples returns true.
2) !(lhs == rhs)
3) true if the first non-equivalent element in lhs is less than the one in rhs, false if the first non-equivalent element in rhs is less than the one in lhs or there is no non-equivalent element. For two empty tuples, returns false.
4) !(rhs < lhs)
5) rhs < lhs
6) !(lhs < rhs)
7) The relation between the first pair of non-equivalent elements if there is any, std::strong_ordering::equal otherwise. For two empty tuples, returns std::strong_ordering::equal.

Example

Because operator< is defined for tuples, containers of tuples can be sorted.

#include <iostream>
#include <tuple>
#include <vector>
#include <algorithm>
int main()
{
    std::vector<std::tuple<int, std::string, float>> v{
        {2, "baz", -0.1},
        {2, "bar", 3.14},
        {1, "foo", 10.1},
        {2, "baz", -1.1},
    };
    std::sort(v.begin(), v.end());
 
    for(const auto& p: v) {
        std::cout << "{" << std::get<0>(p) << ", " << std::get<1>(p)
                  << ", " << std::get<2>(p) << "}\n";
    }
}

Output:

{1, foo, 10.1}
{2, bar, 3.14}
{2, baz, -1.1}
{2, baz, -0.1}

See also

(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)
lexicographically compares the values in the pair
(function template)