Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-114991

QVariant<double> comparison uses <float> on `-qreal float` platforms

    XMLWordPrintable

Details

    • Other
    • 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!

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            vhilshei Volker Hilsheimer
            stevenr3 Steve Rossen
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: