Teach Qt::compareThreeWay() to support native float16 types

Provide a custom variable template to detect float types and
specialize it for QtPrivate::NativeFloat16Type.
This will allow to enable three-way comparison for qfloat16.

Task-number: QTBUG-104113
Change-Id: Id12c42c86f8dc9e233fe39776b0f0e28088de9e1
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
Ivan Solovev 2023-09-26 17:11:03 +02:00
parent d677a454b2
commit 4b755bc11a
2 changed files with 30 additions and 4 deletions

View File

@ -341,6 +341,14 @@ template <typename T>
constexpr bool IsIntegralType_v = std::numeric_limits<std::remove_const_t<T>>::is_specialized
&& std::numeric_limits<std::remove_const_t<T>>::is_integer;
template <typename T>
constexpr bool IsFloatType_v = std::is_floating_point_v<T>;
#if QFLOAT16_IS_NATIVE
template <>
constexpr bool IsFloatType_v<QtPrivate::NativeFloat16Type> = true;
#endif
} // namespace QtPrivate
namespace Qt {
@ -353,14 +361,14 @@ using if_integral =
template <typename T, typename U>
using if_floating_point =
std::enable_if_t<std::conjunction_v<std::is_floating_point<std::remove_reference_t<T>>,
std::is_floating_point<std::remove_reference_t<U>>>,
std::enable_if_t<QtPrivate::IsFloatType_v<std::remove_reference_t<T>>
&& QtPrivate::IsFloatType_v<std::remove_reference_t<U>>,
bool>;
template <typename T, typename U>
using if_integral_and_floating_point =
std::enable_if_t<QtPrivate::IsIntegralType_v<std::remove_reference_t<T>>
&& std::is_floating_point_v<std::remove_reference_t<U>>,
&& QtPrivate::IsFloatType_v<std::remove_reference_t<U>>,
bool>;
template <typename T, typename U>

View File

@ -663,13 +663,31 @@ void tst_QCompareHelpers::builtinOrder()
TEST_BUILTIN(qint64, std::float16_t)
TEST_BUILTIN(uint, std::float16_t)
#endif
TEST_BUILTIN(long double, long double)
TEST_BUILTIN(float, long double)
TEST_BUILTIN(double, long double)
TEST_BUILTIN(quint64, long double)
TEST_BUILTIN(ushort, long double)
#if QFLOAT16_IS_NATIVE
{
// Cannot use TEST_BUILTIN here, because std::numeric_limits are not defined
// for QtPrivate::NativeFloat16Type.
const QtPrivate::NativeFloat16Type smaller{1.0};
const QtPrivate::NativeFloat16Type bigger{2.0};
// native vs native
QCOMPARE_EQ(Qt::compareThreeWay(smaller, smaller), Qt::partial_ordering::equivalent);
QCOMPARE_EQ(Qt::compareThreeWay(smaller, bigger), Qt::partial_ordering::less);
QCOMPARE_EQ(Qt::compareThreeWay(bigger, smaller), Qt::partial_ordering::greater);
// native vs float
QCOMPARE_EQ(Qt::compareThreeWay(smaller, 1.0f), Qt::partial_ordering::equivalent);
QCOMPARE_EQ(Qt::compareThreeWay(1.0f, bigger), Qt::partial_ordering::less);
QCOMPARE_EQ(Qt::compareThreeWay(bigger, 1.0f), Qt::partial_ordering::greater);
const auto floatNaN = std::numeric_limits<float>::quiet_NaN();
QCOMPARE_EQ(Qt::compareThreeWay(bigger, floatNaN), Qt::partial_ordering::unordered);
}
#endif
QCOMPARE_EQ(Qt::compareThreeWay(TestEnum::Smaller, TestEnum::Bigger),
Qt::strong_ordering::less);
QCOMPARE_EQ(Qt::compareThreeWay(TestEnum::Bigger, TestEnum::Smaller),