qnumeric_p.h: fix comparison of signed to unsigned in saturation

qnumeric_p.h:343:18: error: comparison of integers of different signs: 'int' and 'const unsigned int' [-Werror,-Wsign-compare]
   note: in instantiation of function template specialization 'qt_saturate<unsigned int, int>' requested here

Pick-to: 6.4 6.3 6.2
Task-number: QTBUG-104972
Task-number: COIN-928
Change-Id: I810d70e579eb4e2c8e45fffd171992a457a139dc
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
Thiago Macieira 2022-09-30 00:26:11 -07:00 committed by Marc Mutz
parent 2108ddf8f2
commit 6be8efb853
2 changed files with 38 additions and 2 deletions

View File

@ -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 <typename T> static constexpr T max = std::numeric_limits<T>::max();
template <typename T> static constexpr T min = std::numeric_limits<T>::min();
static_assert(qt_saturate<short>(max<unsigned>) == max<short>);
static_assert(qt_saturate<int>(max<unsigned>) == max<int>);
static_assert(qt_saturate<qint64>(max<unsigned>) == qint64(max<unsigned>));
static_assert(qt_saturate<short>(max<int>) == max<short>);
static_assert(qt_saturate<unsigned>(max<int>) == unsigned(max<int>));
static_assert(qt_saturate<qint64>(max<int>) == qint64(max<int>));
static_assert(qt_saturate<short>(max<qint64>) == max<short>);
static_assert(qt_saturate<int>(max<qint64>) == max<int>);
static_assert(qt_saturate<unsigned>(max<qint64>) == max<unsigned>);
static_assert(qt_saturate<quint64>(max<qint64>) == quint64(max<qint64>));
static_assert(qt_saturate<short>(max<quint64>) == max<short>);
static_assert(qt_saturate<int>(max<quint64>) == max<int>);
static_assert(qt_saturate<unsigned>(max<quint64>) == max<unsigned>);
static_assert(qt_saturate<qint64>(max<quint64>) == max<qint64>);
static_assert(qt_saturate<short>(min<int>) == min<short>);
static_assert(qt_saturate<qint64>(min<int>) == qint64(min<int>));
static_assert(qt_saturate<unsigned>(min<int>) == 0);
static_assert(qt_saturate<quint64>(min<int>) == 0);
static_assert(qt_saturate<short>(min<qint64>) == min<short>);
static_assert(qt_saturate<int>(min<qint64>) == min<int>);
static_assert(qt_saturate<unsigned>(min<qint64>) == 0);
static_assert(qt_saturate<quint64>(min<qint64>) == 0);
QT_END_NAMESPACE

View File

@ -322,7 +322,7 @@ template <auto V2, typename T> bool mul_overflow(T v1, T *r)
returns H. Otherwise, returns \c{To(x)}.
*/
template <typename To, typename From>
static auto qt_saturate(From x)
static constexpr auto qt_saturate(From x)
{
static_assert(std::is_integral_v<To>);
static_assert(std::is_integral_v<From>);
@ -332,6 +332,7 @@ static auto qt_saturate(From x)
constexpr auto Hi = (std::numeric_limits<To>::max)();
if constexpr (std::is_signed_v<From> == std::is_signed_v<To>) {
// 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<From>;
using ToU = std::make_unsigned_t<To>;
return FromU(x) > ToU(Hi) ? Hi : To(x); // assumes Hi >= 0
}
}