std::cmp_equal,cmp_not_equal,cmp_less,cmp_greater,cmp_less_equal,cmp_greater_equal(3)

NAME
std::cmp_equal,cmp_not_equal,cmp_less,cmp_greater,cmp_less_equal,cmp_greater_equal - std::cmp_equal,cmp_not_equal,cmp_less,cmp_greater,cmp_less_equal,cmp_greater_equal

Synopsis
   Defined in header <utility>
   template< class T, class U > (1) (since C++20)
   constexpr bool cmp_equal( T t, U u ) noexcept;
   template< class T, class U > (2) (since C++20)
   constexpr bool cmp_not_equal( T t, U u ) noexcept;
   template< class T, class U > (3) (since C++20)
   constexpr bool cmp_less( T t, U u ) noexcept;
   template< class T, class U > (4) (since C++20)
   constexpr bool cmp_greater( T t, U u ) noexcept;
   template< class T, class U > (5) (since C++20)
   constexpr bool cmp_less_equal( T t, U u ) noexcept;
   template< class T, class U > (6) (since C++20)
   constexpr bool cmp_greater_equal( T t, U u ) noexcept;
   Compare the values of two integers t and u. Unlike builtin comparison operators,
   negative signed integers always compare less than (and not equal to) unsigned
   integers: the comparison is safe against lossy integer conversion.
 -1 > 0u; // true
 std::cmp_greater(-1, 0u); // false
   It is a compile-time error if either T or U is not a signed or unsigned integer type
   (including standard integer type and extended integer type).

Parameters
   t - left-hand argument
   u - right-hand argument

Return value
   1) true if t is equal to u.
   2) true if t is not equal to u.
   3) true if t is less than u.
   4) true if t is greater than u.
   5) true if t is less or equal to u.
   6) true if t is greater or equal to u.

Possible implementation
   template< class T, class U >
   constexpr bool cmp_equal( T t, U u ) noexcept
   {
       using UT = std::make_unsigned_t<T>;
       using UU = std::make_unsigned_t<U>;
       if constexpr (std::is_signed_v<T> == std::is_signed_v<U>)
           return t == u;
       else if constexpr (std::is_signed_v<T>)
           return t < 0 ? false : UT(t) == u;
       else
           return u < 0 ? false : t == UU(u);
   }
   template< class T, class U >
   constexpr bool cmp_not_equal( T t, U u ) noexcept
   {
       return !cmp_equal(t, u);
   }
   template< class T, class U >
   constexpr bool cmp_less( T t, U u ) noexcept
   {
       using UT = std::make_unsigned_t<T>;
       using UU = std::make_unsigned_t<U>;
       if constexpr (std::is_signed_v<T> == std::is_signed_v<U>)
           return t < u;
       else if constexpr (std::is_signed_v<T>)
           return t < 0 ? true : UT(t) < u;
       else
           return u < 0 ? false : t < UU(u);
   }
   template< class T, class U >
   constexpr bool cmp_greater( T t, U u ) noexcept
   {
       return cmp_less(u, t);
   }
   template< class T, class U >
   constexpr bool cmp_less_equal( T t, U u ) noexcept
   {
       return !cmp_greater(t, u);
   }
   template< class T, class U >
   constexpr bool cmp_greater_equal( T t, U u ) noexcept
   {
       return !cmp_less(t, u);
   }

Notes
   These functions cannot be used to compare enums (including std::byte), char,
   char8_t, char16_t, char32_t, wchar_t and bool.
   Feature-test macro: __cpp_lib_integer_comparison_functions

Example
   The example below might produce different signedness comparison warning if compiled
   without an appropriate warning suppression flag, e.g. -Wno-sign-compare (gcc/clang
   with -Wall -Wextra, see also SO: disabling a specific warning). // Run this code
 #include <utility>
 // Uncommenting the next line will disable "signed/unsigned comparison" warnings:
 // #pragma GCC diagnostic ignored "-Wsign-compare"
 int main()
 {
     static_assert( sizeof(int) == 4 ); // precondition
     // Quite surprisingly
     static_assert( -1 > 1U ); //< warning: sign-unsign comparison
     // because after implicit conversion of -1 to the RHS type (`unsigned int`)
     // the expression is equivalent to:
     static_assert( 0xFFFFFFFFU > 1U );
     static_assert( 0xFFFFFFFFU == static_cast<unsigned>(-1) );
     // In contrast, the cmp_* family compares integers as most expected -
     // negative signed integers always compare less than unsigned integers:
     static_assert( std::cmp_less( -1, 1U ) );
     static_assert( std::cmp_less_equal( -1, 1U ) );
     static_assert( ! std::cmp_greater( -1, 1U ) );
     static_assert( ! std::cmp_greater_equal( -1, 1U ) );
     static_assert( -1 == 0xFFFFFFFFU ); //< warning: sign-unsign comparison
     static_assert( std::cmp_not_equal( -1, 0xFFFFFFFFU ) );
 }

See also
   equal_to function object implementing x == y
                        (class template)
   not_equal_to function object implementing x != y
                        (class template)
   less function object implementing x < y
                        (class template)
   greater function object implementing x > y
                        (class template)
   less_equal function object implementing x <= y
                        (class template)
   greater_equal function object implementing x >= y
                        (class template)
   ranges::equal_to function object implementing x == y
   (C++20) (class)
   ranges::not_equal_to function object implementing x != y
   (C++20) (class)
   ranges::less function object implementing x < y
   (C++20) (class)
   ranges::greater function object implementing x > y
   (C++20) (class)
   ranges::less_equal function object implementing x <= y
   (C++20) (class)
   ranges::greater_equal function object implementing x >= y
   (C++20) (class)
   compare_three_way function object implementing x <=> y
   (C++20) (class)
   in_range checks if an integer value is in the range of a given integer
   (C++20) type
                        (function template)
                        provides an interface to query properties of all fundamental
   numeric_limits numeric types.
                        (class template)