QVariant/QMetaType: fix conversions to/from qfloat16

Needed to make some conversions explicit, since you can't assign to a
qfloat16 from double.

[ChangeLog][QtCore][QVariant] Implemented converting of qfloat16 to and
from the other numeric types, text conversions to and from QString and
QByteArray, and conversions to and from QJsonValue and QCborValue. This
should make qfloat16 behave the same as float and double.

Also flip the order of arguments in one of the addComparePairs(): left
side is actual, right side is expected. I noticed on the copy & paste
to do the qfloat16 above it.

Pick-to: 6.8
Task-number: QTBUG-134756
Change-Id: I6a6c469d21746a07c18efffd6b3b961c73c0e2f2
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
(cherry picked from commit a4daf4939644ea3a087a8c03b1ec962e2e4defa8)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Thiago Macieira 2025-03-17 11:35:09 -07:00 committed by Qt Cherry-pick Bot
parent f754cd0ce9
commit 469c071d69
3 changed files with 55 additions and 6 deletions

View File

@ -1004,6 +1004,7 @@ static constexpr struct : QMetaTypeModuleHelper
using LongLong = qlonglong;
using ULong = unsigned long;
using ULongLong = qulonglong;
using Float16 = qfloat16;
using Float = float;
using Double = double;
using Bool = bool;
@ -1028,7 +1029,7 @@ static constexpr struct : QMetaTypeModuleHelper
if constexpr(std::is_integral_v<To>) \
result = source.toInteger(); \
else \
result = source.toDouble(); \
result = To(source.toDouble()); \
} \
return true; \
); \
@ -1043,7 +1044,7 @@ static constexpr struct : QMetaTypeModuleHelper
if constexpr(std::is_integral_v<To>) \
result = source.toInteger(); \
else \
result = source.toDouble(); \
result = To(source.toDouble()); \
} \
return true; \
)
@ -1064,6 +1065,7 @@ static constexpr struct : QMetaTypeModuleHelper
QMETATYPE_CONVERTER_ASSIGN(To, ULong); \
QMETATYPE_CONVERTER_ASSIGN(To, LongLong); \
QMETATYPE_CONVERTER_ASSIGN(To, ULongLong); \
QMETATYPE_CONVERTER(To, Float16, result = qRound64(source); return true;); \
QMETATYPE_CONVERTER(To, Float, result = qRound64(source); return true;); \
QMETATYPE_CONVERTER(To, Double, result = qRound64(source); return true;); \
QMETATYPE_CONVERTER(To, QChar, result = source.unicode(); return true;); \
@ -1102,16 +1104,17 @@ static constexpr struct : QMetaTypeModuleHelper
QMETATYPE_CONVERTER_ASSIGN(To, ULong); \
QMETATYPE_CONVERTER_ASSIGN(To, LongLong); \
QMETATYPE_CONVERTER_ASSIGN(To, ULongLong); \
QMETATYPE_CONVERTER_ASSIGN(To, Float16); \
QMETATYPE_CONVERTER_ASSIGN(To, Float); \
QMETATYPE_CONVERTER_ASSIGN(To, Double); \
QMETATYPE_CONVERTER(To, QString, \
bool ok = false; \
result = source.toDouble(&ok); \
result = To(source.toDouble(&ok)); \
return ok; \
); \
QMETATYPE_CONVERTER(To, QByteArray, \
bool ok = false; \
result = source.toDouble(&ok); \
result = To(source.toDouble(&ok)); \
return ok; \
); \
CONVERT_CBOR_AND_JSON(To)
@ -1131,6 +1134,7 @@ static constexpr struct : QMetaTypeModuleHelper
INTEGRAL_CONVERTER(ULong);
INTEGRAL_CONVERTER(LongLong);
INTEGRAL_CONVERTER(ULongLong);
FLOAT_CONVERTER(Float16);
FLOAT_CONVERTER(Float);
FLOAT_CONVERTER(Double);
@ -1182,6 +1186,10 @@ static constexpr struct : QMetaTypeModuleHelper
QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, ULong);
QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, UInt);
QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, ULongLong);
QMETATYPE_CONVERTER(QString, Float16,
result = QString::number(source, 'g', QLocale::FloatingPointShortest);
return true;
);
QMETATYPE_CONVERTER(QString, Float,
result = QString::number(source, 'g', QLocale::FloatingPointShortest);
return true;
@ -1250,6 +1258,10 @@ static constexpr struct : QMetaTypeModuleHelper
QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, ULong);
QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, UInt);
QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, ULongLong);
QMETATYPE_CONVERTER(QByteArray, Float16,
result = QByteArray::number(source, 'g', QLocale::FloatingPointShortest);
return true;
);
QMETATYPE_CONVERTER(QByteArray, Float,
result = QByteArray::number(source, 'g', QLocale::FloatingPointShortest);
return true;
@ -1393,6 +1405,7 @@ static constexpr struct : QMetaTypeModuleHelper
QMETATYPE_CONVERTER_ASSIGN(QCborValue, Short);
QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QCborValue, Double);
QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QCborValue, Float);
QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QCborValue, Float16);
QMETATYPE_CONVERTER(QCborValue, QStringList,
result = QCborArray::fromStringList(source);
return true;
@ -1583,6 +1596,7 @@ static constexpr struct : QMetaTypeModuleHelper
QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, UInt);
QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Double);
QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Float);
QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Float16);
QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, ULong);
QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Long);
QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, LongLong);

View File

@ -2210,6 +2210,7 @@ static bool qIsNumericType(uint tp)
Q_UINT64_C(1) << QMetaType::QString |
Q_UINT64_C(1) << QMetaType::Bool |
Q_UINT64_C(1) << QMetaType::Double |
Q_UINT64_C(1) << QMetaType::Float16 |
Q_UINT64_C(1) << QMetaType::Float |
Q_UINT64_C(1) << QMetaType::Char |
Q_UINT64_C(1) << QMetaType::Char16 |

View File

@ -260,6 +260,9 @@ private slots:
void toFloat_data();
void toFloat();
void toFloat16_data();
void toFloat16();
void toPointF_data();
void toPointF();
@ -893,6 +896,7 @@ template <typename To> static void addNumberConversions()
addNumber(0x8000'0000UL);
addNumber(-0x1'0000'0000LL);
addNumber(0x1'0000'000'0000ULL);
addNumber(qfloat16(-3.1415927f));
addNumber(-3.1415927f);
addNumber(-3.1415927);
@ -1145,8 +1149,10 @@ void tst_QVariant::toBool_data()
QTest::newRow( "uint1" ) << QVariant( 123u ) << true;
QTest::newRow( "double0" ) << QVariant( 0.0 ) << false;
QTest::newRow( "float0" ) << QVariant( 0.0f ) << false;
QTest::newRow( "float16_0" ) << QVariant::fromValue( qfloat16() ) << false;
QTest::newRow( "double1" ) << QVariant( 3.1415927 ) << true;
QTest::newRow( "float1" ) << QVariant( 3.1415927f ) << true;
QTest::newRow( "float16_1" ) << QVariant::fromValue( qfloat16(3.1415927f) ) << true;
QTest::newRow( "string0" ) << QVariant( QString("3") ) << true;
QTest::newRow( "string1" ) << QVariant( QString("true") ) << true;
QTest::newRow( "string2" ) << QVariant( QString("0") ) << false;
@ -1238,6 +1244,16 @@ void tst_QVariant::toFloat()
checkNumberConversions(&QVariant::toFloat);
}
void tst_QVariant::toFloat16_data()
{
addNumberConversions<qfloat16>();
}
void tst_QVariant::toFloat16()
{
checkNumberConversions<qfloat16>(nullptr);
}
void tst_QVariant::toSChar_data()
{
addNumberConversions<signed char>();
@ -3020,6 +3036,7 @@ void tst_QVariant::compareNumerics_data() const
addCompareToInvalid(ulong(0));
addCompareToInvalid(qint64(0));
addCompareToInvalid(quint64(0));
addCompareToInvalid(qfloat16(0.f));
addCompareToInvalid(0.f);
addCompareToInvalid(0.0);
addCompareToInvalid(QCborSimpleType{});
@ -3060,7 +3077,7 @@ QT_WARNING_POP
T one = T(zero + 1);
T min = std::numeric_limits<T>::min();
T max = std::numeric_limits<T>::max();
T mid = max / 2 + 1;
T mid = T(max / 2 + 1);
if (min != zero)
addList(std::array{zero, one, min, mid, max});
else
@ -3079,6 +3096,7 @@ QT_WARNING_POP
addSingleType(quint32(0));
addSingleType(qint64(0));
addSingleType(quint64(0));
addSingleType(qfloat16(0.f));
addSingleType(0.f);
addSingleType(0.0);
addList(std::array{ EnumTest_Enum0{}, EnumTest_Enum0_value, EnumTest_Enum0_negValue });
@ -3138,6 +3156,22 @@ QT_WARNING_POP
// addComparePair(LLONG_MIN, LLONG_MAX); // already added by addSingleType()
// floating point
addComparePair(qfloat16(0.f), 0);
addComparePair(qfloat16(0.f), 0U);
addComparePair(qfloat16(0.f), Q_INT64_C(0));
addComparePair(qfloat16(0.f), Q_UINT64_C(0));
addComparePair(qfloat16(0.f), 0.f);
addComparePair(qfloat16(0.f), 1.f);
addComparePair(qfloat16(0.f), 0.);
addComparePair(qfloat16(0.f), 1.);
addComparePair(qfloat16(1 << 11), 1 << 11);
addComparePair(qfloat16(1 << 11) - 1, (1 << 11) - 1);
addComparePair(-qfloat16(1 << 11), 1 << 11);
addComparePair(-qfloat16(1 << 11) + 1, -(1 << 11) + 1);
addComparePair(std::numeric_limits<qfloat16>::infinity(), qInf());
addComparePair(std::numeric_limits<qfloat16>::infinity(), -qInf());
addComparePair(std::numeric_limits<qfloat16>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN());
addComparePair(0.f, 0);
addComparePair(0.f, 0U);
addComparePair(0.f, Q_INT64_C(0));
@ -3150,7 +3184,7 @@ QT_WARNING_POP
addComparePair(-float(1 << 24) + 1, -(1 << 24) + 1);
addComparePair(HUGE_VALF, qInf());
addComparePair(HUGE_VALF, -qInf());
addComparePair(qQNaN(), std::numeric_limits<float>::quiet_NaN());
addComparePair(std::numeric_limits<float>::quiet_NaN(), qQNaN());
if (sizeof(qreal) == sizeof(double)) {
addComparePair(std::numeric_limits<float>::min(), std::numeric_limits<double>::min());
addComparePair(std::numeric_limits<float>::min(), std::numeric_limits<double>::max());