Details
-
Bug
-
Resolution: Fixed
-
P3: Somewhat important
-
5.15.13
-
-
1fe60cbcc (dev), a20107433 (6.5), f00f557ee (6.6), 87d46ab30 (tqtc/lts-6.2), 1a03c6415 (tqtc/lts-5.15)
Description
The following unit tests demonstrates what I believe is a bug in QVariant<double> equality comparisons (== and !=) on platforms with `-qreal float` defined. Works as expected on platforms without `-qreal float` defined.
The tests show that different double data inside the variants may wrongly compare as being equal.
Note - the double values are only slightly different, such that if they were <float> they would be equal.
I would understand if QVariant<qreal> (or QVariant<float>) compare behaved this way - but not when using explicit QVariant<double>.
TEST(QVariantDouble, DifferentVariantFromDoubleCompareNotEqual) { EXPECT_NE(QVariant::fromValue<double>(-1.6678526196964594), QVariant::fromValue<double>(-1.6678458552359494)); } TEST(QVariantDouble, DifferentVariantFromDoubleToDoubleCompareNotEqual) { EXPECT_NE(QVariant::fromValue<double>(-1.6678526196964594).toDouble(), QVariant::fromValue<double>(-1.6678458552359494).toDouble()); }
Test output:
[ RUN ] QVariantDouble.DifferentVariantFromDoubleCompareNotEqual ../../../Test.cpp:109: Failure Expected: (QVariant::fromValue<double>(-1.6678526196964594)) != (QVariant::fromValue<double>(-1.6678458552359494)), actual: 16-byte object <B8-4E 82-3A 86-AF FA-BF 06-00 00-00 00-DE 8E-00> vs 16-byte object <F0-1E B0-22 7F-AF FA-BF 06-00 00-00 8C-DD 8E-00> [ FAILED ] QVariantDouble.DifferentVariantFromDoubleCompareNotEqual (0 ms) [ RUN ] QVariantDouble.DifferentVariantFromDoubleToDoubleCompareNotEqual [ OK ] QVariantDouble.DifferentVariantFromDoubleToDoubleCompareNotEqual (0 ms)
I beleive the problem lies in
bool QVariant::cmp(const QVariant &v) const ... // try numerics first, with C++ type promotion rules (no conversion) if (qIsNumericType(d.type) && qIsNumericType(v.d.type)) >> return numericCompare(&d, &v.d) == 0;
static int numericCompare(const QVariant::Private *d1, const QVariant::Private *d2) { uint promotedType = numericTypePromotion(d1->type, d2->type); if (promotedType != QMetaType::QReal) return integralCompare(promotedType, d1, d2); // qreal comparisons <<<<<<<<<<<<<<<<<<<<<< bool ok; qreal r1 = qConvertToRealNumber(d1, &ok); Q_ASSERT(ok); qreal r2 = qConvertToRealNumber(d2, &ok);
QVariant<double> is doing <qreal> aka <qfloat> comparison on `-qreal float` platforms!