qfloat16: make relational operators constexpr when QFLOAT16_IS_NATIVE

When qfloat16 uses float as an underlying type, the operators cannot be
constexpr, because operator float() is not constexpr.
However, operator NativeType() is, so we can make the relational
operators constexpr when we are using a native 16-bit float as an
underlying type.

To avoid code duplication, introduce new temporary macros for
constexpr and Q_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE.
Extend the tests to verify that the operators are constexpr when
native float16 type is used.

Task-number: QTBUG-119433
Change-Id: I001b087d78c398c71b71a504b65c316199dd4792
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
(cherry picked from commit cfc385ce3fc674d48ea2bfbaac6d3f907795b1a5)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Ivan Solovev 2023-12-19 17:40:28 +01:00 committed by Qt Cherry-pick Bot
parent c112981789
commit 84fde7ef2f
2 changed files with 73 additions and 20 deletions

View File

@ -182,18 +182,28 @@ private:
QT_WARNING_PUSH
QT_WARNING_DISABLE_FLOAT_COMPARE
friend bool comparesEqual(const qfloat16 &lhs, const qfloat16 &rhs) noexcept
#if QFLOAT16_IS_NATIVE
# define QF16_CONSTEXPR constexpr
# define QF16_PARTIALLY_ORDERED Q_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE
#else
# define QF16_CONSTEXPR
# define QF16_PARTIALLY_ORDERED Q_DECLARE_PARTIALLY_ORDERED
#endif
friend QF16_CONSTEXPR bool comparesEqual(const qfloat16 &lhs, const qfloat16 &rhs) noexcept
{ return static_cast<NearestFloat>(lhs) == static_cast<NearestFloat>(rhs); }
friend Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, const qfloat16 &rhs) noexcept
friend QF16_CONSTEXPR
Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, const qfloat16 &rhs) noexcept
{ return Qt::compareThreeWay(static_cast<NearestFloat>(lhs), static_cast<NearestFloat>(rhs)); }
Q_DECLARE_PARTIALLY_ORDERED(qfloat16)
QF16_PARTIALLY_ORDERED(qfloat16)
#define QF16_MAKE_ORDER_OP_FP(FP) \
friend bool comparesEqual(const qfloat16 &lhs, FP rhs) noexcept \
friend QF16_CONSTEXPR bool comparesEqual(const qfloat16 &lhs, FP rhs) noexcept \
{ return static_cast<FP>(lhs) == rhs; } \
friend Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, FP rhs) noexcept \
friend QF16_CONSTEXPR \
Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, FP rhs) noexcept \
{ return Qt::compareThreeWay(static_cast<FP>(lhs), rhs); } \
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, FP)
QF16_PARTIALLY_ORDERED(qfloat16, FP)
QF16_MAKE_ORDER_OP_FP(long double)
QF16_MAKE_ORDER_OP_FP(double)
@ -204,27 +214,30 @@ QT_WARNING_DISABLE_FLOAT_COMPARE
#undef QF16_MAKE_ORDER_OP_FP
template <typename T, if_type_is_integral<T> = true>
friend bool comparesEqual(const qfloat16 &lhs, T rhs) noexcept
friend QF16_CONSTEXPR bool comparesEqual(const qfloat16 &lhs, T rhs) noexcept
{ return static_cast<NearestFloat>(lhs) == static_cast<NearestFloat>(rhs); }
template <typename T, if_type_is_integral<T> = true>
friend Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, T rhs) noexcept
friend QF16_CONSTEXPR Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, T rhs) noexcept
{ return Qt::compareThreeWay(static_cast<NearestFloat>(lhs), static_cast<NearestFloat>(rhs)); }
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, qint8)
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, quint8)
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, qint16)
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, quint16)
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, qint32)
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, quint32)
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, long)
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, unsigned long)
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, qint64)
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, quint64)
QF16_PARTIALLY_ORDERED(qfloat16, qint8)
QF16_PARTIALLY_ORDERED(qfloat16, quint8)
QF16_PARTIALLY_ORDERED(qfloat16, qint16)
QF16_PARTIALLY_ORDERED(qfloat16, quint16)
QF16_PARTIALLY_ORDERED(qfloat16, qint32)
QF16_PARTIALLY_ORDERED(qfloat16, quint32)
QF16_PARTIALLY_ORDERED(qfloat16, long)
QF16_PARTIALLY_ORDERED(qfloat16, unsigned long)
QF16_PARTIALLY_ORDERED(qfloat16, qint64)
QF16_PARTIALLY_ORDERED(qfloat16, quint64)
#ifdef QT_SUPPORTS_INT128
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, qint128)
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, quint128)
QF16_PARTIALLY_ORDERED(qfloat16, qint128)
QF16_PARTIALLY_ORDERED(qfloat16, quint128)
#endif
#undef QF16_PARTIALLY_ORDERED
#undef QF16_CONSTEXPR
QT_WARNING_POP
#ifndef QT_NO_DATASTREAM

View File

@ -21,6 +21,7 @@ class tst_qfloat16: public QObject
private slots:
void compareCompiles();
void relationalOperatorsAreConstexpr();
void ordering_data();
void ordering();
void fuzzyCompare_data();
@ -80,6 +81,45 @@ void tst_qfloat16::compareCompiles()
#endif
}
void tst_qfloat16::relationalOperatorsAreConstexpr()
{
#if QFLOAT16_IS_NATIVE
#define CHECK_CONSTEXPR(Type) \
do { \
constexpr qfloat16 lhs = qfloat16(0.0f); \
constexpr Type rhs = 1; \
static_assert(lhs < rhs); \
static_assert(rhs >= lhs); \
} while (false)
CHECK_CONSTEXPR(qfloat16);
CHECK_CONSTEXPR(float);
CHECK_CONSTEXPR(double);
CHECK_CONSTEXPR(long double);
CHECK_CONSTEXPR(qfloat16::NativeType);
CHECK_CONSTEXPR(qint8);
CHECK_CONSTEXPR(quint8);
CHECK_CONSTEXPR(qint16);
CHECK_CONSTEXPR(quint16);
CHECK_CONSTEXPR(qint32);
CHECK_CONSTEXPR(quint32);
CHECK_CONSTEXPR(long);
CHECK_CONSTEXPR(unsigned long);
CHECK_CONSTEXPR(qint64);
CHECK_CONSTEXPR(quint64);
#ifdef QT_SUPPORTS_INT128
CHECK_CONSTEXPR(qint128);
CHECK_CONSTEXPR(quint128);
#endif
#undef CHECK_CONSTEXPR
#else
QSKIP("This check is only relevant for native float16 types");
#endif // QFLOAT16_IS_NATIVE
}
void tst_qfloat16::ordering_data()
{
QTest::addColumn<float>("left");