diff --git a/src/corelib/global/qnumeric.cpp b/src/corelib/global/qnumeric.cpp index 16b2b7ca408..e492e3f02a0 100644 --- a/src/corelib/global/qnumeric.cpp +++ b/src/corelib/global/qnumeric.cpp @@ -458,4 +458,35 @@ Q_CORE_EXPORT quint64 qFloatDistance(double a, double b) Returns true if the absolute value of \a f is within 0.00001f of 0.0. */ +template static constexpr T max = std::numeric_limits::max(); +template static constexpr T min = std::numeric_limits::min(); + +static_assert(qt_saturate(max) == max); +static_assert(qt_saturate(max) == max); +static_assert(qt_saturate(max) == qint64(max)); + +static_assert(qt_saturate(max) == max); +static_assert(qt_saturate(max) == unsigned(max)); +static_assert(qt_saturate(max) == qint64(max)); + +static_assert(qt_saturate(max) == max); +static_assert(qt_saturate(max) == max); +static_assert(qt_saturate(max) == max); +static_assert(qt_saturate(max) == quint64(max)); + +static_assert(qt_saturate(max) == max); +static_assert(qt_saturate(max) == max); +static_assert(qt_saturate(max) == max); +static_assert(qt_saturate(max) == max); + +static_assert(qt_saturate(min) == min); +static_assert(qt_saturate(min) == qint64(min)); +static_assert(qt_saturate(min) == 0); +static_assert(qt_saturate(min) == 0); + +static_assert(qt_saturate(min) == min); +static_assert(qt_saturate(min) == min); +static_assert(qt_saturate(min) == 0); +static_assert(qt_saturate(min) == 0); + QT_END_NAMESPACE diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h index 8e08615ab37..f5beb4d38de 100644 --- a/src/corelib/global/qnumeric_p.h +++ b/src/corelib/global/qnumeric_p.h @@ -322,7 +322,7 @@ template bool mul_overflow(T v1, T *r) returns H. Otherwise, returns \c{To(x)}. */ template -static auto qt_saturate(From x) +static constexpr auto qt_saturate(From x) { static_assert(std::is_integral_v); static_assert(std::is_integral_v); @@ -332,6 +332,7 @@ static auto qt_saturate(From x) constexpr auto Hi = (std::numeric_limits::max)(); if constexpr (std::is_signed_v == std::is_signed_v) { + // same signedness, we can accept regular integer conversion rules return x < Lo ? Lo : x > Hi ? Hi : /*else*/ To(x); @@ -340,7 +341,11 @@ static auto qt_saturate(From x) if (x < From{0}) return To{0}; } - return x > Hi ? Hi : To(x); + + // from here on, x >= 0 + using FromU = std::make_unsigned_t; + using ToU = std::make_unsigned_t; + return FromU(x) > ToU(Hi) ? Hi : To(x); // assumes Hi >= 0 } }