Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/utility/intcmp"

From cppreference.com
< cpp‎ | utility
m (Notes: ~FTM)
m (fmt, {{c}})
Line 3: Line 3:
  
 
{{dcl begin}}
 
{{dcl begin}}
{{dcl header | utility }}
+
{{dcl header|utility}}
{{dcl | num=1 | since=c++20 | 1=
+
{{dcl|num=1|since=c++20|1=
 
template< class T, class U >
 
template< class T, class U >
 
constexpr bool cmp_equal( T t, U u ) noexcept;
 
constexpr bool cmp_equal( T t, U u ) noexcept;
 
}}
 
}}
{{dcl | num=2 | since=c++20 | 1=
+
{{dcl|num=2|since=c++20|1=
 
template< class T, class U >
 
template< class T, class U >
 
constexpr bool cmp_not_equal( T t, U u ) noexcept;
 
constexpr bool cmp_not_equal( T t, U u ) noexcept;
 
}}
 
}}
{{dcl | num=3 | since=c++20 | 1=
+
{{dcl|num=3|since=c++20|1=
 
template< class T, class U >
 
template< class T, class U >
 
constexpr bool cmp_less( T t, U u ) noexcept;
 
constexpr bool cmp_less( T t, U u ) noexcept;
 
}}
 
}}
{{dcl | num=4 | since=c++20 | 1=
+
{{dcl|num=4|since=c++20|1=
 
template< class T, class U >
 
template< class T, class U >
 
constexpr bool cmp_greater( T t, U u ) noexcept;
 
constexpr bool cmp_greater( T t, U u ) noexcept;
 
}}
 
}}
{{dcl | num=5 | since=c++20 | 1=
+
{{dcl|num=5|since=c++20|1=
 
template< class T, class U >
 
template< class T, class U >
 
constexpr bool cmp_less_equal( T t, U u ) noexcept;
 
constexpr bool cmp_less_equal( T t, U u ) noexcept;
 
}}
 
}}
{{dcl | num=6 | since=c++20 | 1=
+
{{dcl|num=6|since=c++20|1=
 
template< class T, class U >
 
template< class T, class U >
 
constexpr bool cmp_greater_equal( T t, U u ) noexcept;
 
constexpr bool cmp_greater_equal( T t, U u ) noexcept;
Line 30: Line 30:
 
{{dcl end}}
 
{{dcl end}}
  
Compare the values of two integers {{tt|t}} and {{tt|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.
+
Compare the values of two integers {{c|t}} and {{c|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.
  
 
{{source|1=
 
{{source|1=
Line 41: Line 41:
 
===Parameters===
 
===Parameters===
 
{{par begin}}
 
{{par begin}}
{{par | t | left-hand argument}}
+
{{par|t|left-hand argument}}
{{par | u | right-hand argument}}
+
{{par|u|right-hand argument}}
 
{{par end}}
 
{{par end}}
  
 
===Return value===
 
===Return value===
@1@ {{c|true}} if {{tt|t}} is equal to {{tt|u}}.
+
@1@ {{c|true}} if {{c|t}} is equal to {{c|u}}.
@2@ {{c|true}} if {{tt|t}} is not equal to {{tt|u}}.
+
@2@ {{c|true}} if {{c|t}} is not equal to {{c|u}}.
@3@ {{c|true}} if {{tt|t}} is less than {{tt|u}}.
+
@3@ {{c|true}} if {{c|t}} is less than {{c|u}}.
@4@ {{c|true}} if {{tt|t}} is greater than {{tt|u}}.
+
@4@ {{c|true}} if {{c|t}} is greater than {{c|u}}.
@5@ {{c|true}} if {{tt|t}} is less or equal to {{tt|u}}.
+
@5@ {{c|true}} if {{c|t}} is less or equal to {{c|u}}.
@6@ {{c|true}} if {{tt|t}} is greater or equal to {{tt|u}}.
+
@6@ {{c|true}} if {{c|t}} is greater or equal to {{c|u}}.
  
 
===Possible implementation===
 
===Possible implementation===
 
{{eq fun|1=
 
{{eq fun|1=
template< class T, class U >
+
template<class T, class U>
constexpr bool cmp_equal( T t, U u ) noexcept
+
constexpr bool cmp_equal(T t, U u) noexcept
 
{
 
{
 
     using UT = std::make_unsigned_t<T>;
 
     using UT = std::make_unsigned_t<T>;
Line 68: Line 68:
 
}
 
}
  
template< class T, class U >
+
template<class T, class U>
constexpr bool cmp_not_equal( T t, U u ) noexcept
+
constexpr bool cmp_not_equal(T t, U u) noexcept
 
{
 
{
 
     return !cmp_equal(t, u);
 
     return !cmp_equal(t, u);
 
}
 
}
  
template< class T, class U >
+
template<class T, class U>
constexpr bool cmp_less( T t, U u ) noexcept
+
constexpr bool cmp_less(T t, U u) noexcept
 
{
 
{
 
     using UT = std::make_unsigned_t<T>;
 
     using UT = std::make_unsigned_t<T>;
Line 87: Line 87:
 
}
 
}
  
template< class T, class U >
+
template<class T, class U>
constexpr bool cmp_greater( T t, U u ) noexcept
+
constexpr bool cmp_greater(T t, U u) noexcept
 
{
 
{
 
     return cmp_less(u, t);
 
     return cmp_less(u, t);
 
}
 
}
  
template< class T, class U >
+
template<class T, class U>
constexpr bool cmp_less_equal( T t, U u ) noexcept
+
constexpr bool cmp_less_equal(T t, U u) noexcept
 
{
 
{
 
     return !cmp_greater(t, u);
 
     return !cmp_greater(t, u);
 
}
 
}
  
template< class T, class U >
+
template<class T, class U>
constexpr bool cmp_greater_equal( T t, U u ) noexcept
+
constexpr bool cmp_greater_equal(T t, U u) noexcept
 
{
 
{
 
     return !cmp_less(t, u);
 
     return !cmp_less(t, u);
Line 112: Line 112:
 
===Example===
 
===Example===
 
{{example
 
{{example
| The example below might produce ''different signedness comparison'' warning if compiled without an appropriate warning suppression flag, e.g., {{tt|-Wno-sign-compare}} (gcc/clang with {{tt|-Wall -Wextra}}, see also [https://stackoverflow.com/questions/3378560 SO: disabling a specific warning]).
+
|The example below might produce ''different signedness comparison'' warning if compiled without an appropriate warning suppression flag, e.g., {{tt|-Wno-sign-compare}} (gcc/clang with {{tt|-Wall -Wextra}}, see also [https://stackoverflow.com/questions/3378560 SO: disabling a specific warning]).
 
|code=
 
|code=
 
#include <utility>
 
#include <utility>
Line 121: Line 121:
 
int main()
 
int main()
 
{
 
{
     static_assert( sizeof(int) == 4 ); // precondition
+
     static_assert(sizeof(int) == 4); // precondition
  
 
     // Quite surprisingly
 
     // Quite surprisingly
     static_assert( -1 > 1U ); //< warning: sign-unsign comparison
+
     static_assert(-1 > 1U); //< warning: sign-unsign comparison
 
     // because after implicit conversion of -1 to the RHS type (`unsigned int`)
 
     // because after implicit conversion of -1 to the RHS type (`unsigned int`)
 
     // the expression is equivalent to:
 
     // the expression is equivalent to:
     static_assert( 0xFFFFFFFFU > 1U );
+
     static_assert(0xFFFFFFFFU > 1U);
     static_assert( 0xFFFFFFFFU == static_cast<unsigned>(-1) );
+
     static_assert(0xFFFFFFFFU == static_cast<unsigned>(-1));
  
 
     // In contrast, the cmp_* family compares integers as most expected -
 
     // In contrast, the cmp_* family compares integers as most expected -
 
     // negative signed integers always compare less than unsigned integers:
 
     // negative signed integers always compare less than unsigned integers:
     static_assert( std::cmp_less( -1, 1U ) );
+
     static_assert(std::cmp_less(-1, 1U));
     static_assert( std::cmp_less_equal( -1, 1U ) );
+
     static_assert(std::cmp_less_equal(-1, 1U));
     static_assert( ! std::cmp_greater( -1, 1U ) );
+
     static_assert(!std::cmp_greater(-1, 1U));
     static_assert( ! std::cmp_greater_equal( -1, 1U ) );
+
     static_assert(!std::cmp_greater_equal(-1, 1U));
  
     static_assert( -1 == 0xFFFFFFFFU ); //< warning: sign-unsign comparison
+
     static_assert(-1 == 0xFFFFFFFFU); //< warning: sign-unsign comparison
     static_assert( std::cmp_not_equal( -1, 0xFFFFFFFFU ) );
+
     static_assert(std::cmp_not_equal(-1, 0xFFFFFFFFU));
 
}
 
}
 
}}
 
}}
Line 144: Line 144:
 
===See also===
 
===See also===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc inc | cpp/utility/functional/dsc equal_to}}
+
{{dsc inc|cpp/utility/functional/dsc equal_to}}
{{dsc inc | cpp/utility/functional/dsc not_equal_to}}
+
{{dsc inc|cpp/utility/functional/dsc not_equal_to}}
{{dsc inc | cpp/utility/functional/dsc less}}
+
{{dsc inc|cpp/utility/functional/dsc less}}
{{dsc inc | cpp/utility/functional/dsc greater}}
+
{{dsc inc|cpp/utility/functional/dsc greater}}
{{dsc inc | cpp/utility/functional/dsc less_equal}}
+
{{dsc inc|cpp/utility/functional/dsc less_equal}}
{{dsc inc | cpp/utility/functional/dsc greater_equal}}
+
{{dsc inc|cpp/utility/functional/dsc greater_equal}}
{{dsc inc | cpp/utility/functional/ranges/dsc equal_to}}
+
{{dsc inc|cpp/utility/functional/ranges/dsc equal_to}}
{{dsc inc | cpp/utility/functional/ranges/dsc not_equal_to}}
+
{{dsc inc|cpp/utility/functional/ranges/dsc not_equal_to}}
{{dsc inc | cpp/utility/functional/ranges/dsc less}}
+
{{dsc inc|cpp/utility/functional/ranges/dsc less}}
{{dsc inc | cpp/utility/functional/ranges/dsc greater}}
+
{{dsc inc|cpp/utility/functional/ranges/dsc greater}}
{{dsc inc | cpp/utility/functional/ranges/dsc less_equal}}
+
{{dsc inc|cpp/utility/functional/ranges/dsc less_equal}}
{{dsc inc | cpp/utility/functional/ranges/dsc greater_equal}}
+
{{dsc inc|cpp/utility/functional/ranges/dsc greater_equal}}
{{dsc inc | cpp/utility/compare/dsc compare_three_way}}
+
{{dsc inc|cpp/utility/compare/dsc compare_three_way}}
{{dsc inc | cpp/utility/dsc in_range}}
+
{{dsc inc|cpp/utility/dsc in_range}}
{{dsc inc | cpp/types/dsc numeric_limits}}
+
{{dsc inc|cpp/types/dsc numeric_limits}}
 
{{dsc end}}
 
{{dsc end}}
  
 
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}
 
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}

Revision as of 09:53, 25 May 2023

 
 
Utilities library
General utilities
Relational operators (deprecated in C++20)
Integer comparison functions
cmp_equalcmp_lesscmp_less_than
(C++20)(C++20)(C++20)  
cmp_not_equalcmp_greatercmp_greater_than
(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)

 
Defined in header <utility>
template< class T, class U >
constexpr bool cmp_equal( T t, U u ) noexcept;
(1) (since C++20)
template< class T, class U >
constexpr bool cmp_not_equal( T t, U u ) noexcept;
(2) (since C++20)
template< class T, class U >
constexpr bool cmp_less( T t, U u ) noexcept;
(3) (since C++20)
template< class T, class U >
constexpr bool cmp_greater( T t, U u ) noexcept;
(4) (since C++20)
template< class T, class U >
constexpr bool cmp_less_equal( T t, U u ) noexcept;
(5) (since C++20)
template< class T, class U >
constexpr bool cmp_greater_equal( T t, U u ) noexcept;
(6) (since C++20)

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).

Contents

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 Value Std Feature
__cpp_lib_integer_comparison_functions 202002L (C++20)

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).

#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

function object implementing x == y
(class template) [edit]
function object implementing x != y
(class template) [edit]
function object implementing x < y
(class template) [edit]
function object implementing x > y
(class template) [edit]
function object implementing x <= y
(class template) [edit]
function object implementing x >= y
(class template) [edit]
constrained function object implementing x == y
(class) [edit]
constrained function object implementing x != y
(class) [edit]
constrained function object implementing x < y
(class) [edit]
constrained function object implementing x > y
(class) [edit]
constrained function object implementing x <= y
(class) [edit]
constrained function object implementing x >= y
(class) [edit]
constrained function object implementing x <=> y
(class) [edit]
(C++20)
checks if an integer value is in the range of a given integer type
(function template) [edit]
provides an interface to query properties of all fundamental numeric types
(class template) [edit]