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 non-value-preserving integer conversion.
 -1 > 0u; // true
 std::cmp_greater(-1, 0u); // false
   It is a compile-time error if either T or U is a non-integer type, a character type,
   or bool.

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
   {
       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 && std::make_unsigned_t<T>(t) == u;
       else
           return u >= 0 && std::make_unsigned_t<U>(u) == t;
   }
   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
   {
       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 || std::make_unsigned_t<T>(t) < u;
       else
           return u >= 0 && t < std::make_unsigned_t<U>(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_less(u, t);
   }
   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 Value Std Feature
   __cpp_lib_integer_comparison_functions 202002L (C++20) 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 constrained function object implementing x == y
   (C++20) (class)
   ranges::not_equal_to constrained function object implementing x != y
   (C++20) (class)
   ranges::less constrained function object implementing x < y
   (C++20) (class)
   ranges::greater constrained function object implementing x > y
   (C++20) (class)
   ranges::less_equal constrained function object implementing x <= y
   (C++20) (class)
   ranges::greater_equal constrained function object implementing x >= y
   (C++20) (class)
   compare_three_way constrained 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)