diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index 48e8aed5f5b..123d62168b5 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -2742,6 +2742,16 @@ QString QCborValueConstRef::concreteString(QCborValueConstRef self, const QStrin return self.d->stringAt(self.i); } +bool comparesEqual(const QCborValueConstRef &lhs, const QCborValueConstRef &rhs) noexcept +{ + return lhs.compare(rhs.concrete()) == 0; +} + +bool comparesEqual(const QCborValueConstRef &lhs, const QCborValue &rhs) noexcept +{ + return lhs.compare(rhs) == 0; +} + QCborValue QCborValueConstRef::concrete(QCborValueConstRef self) noexcept { return self.d->valueAt(self.i); diff --git a/src/corelib/serialization/qcborvalue.h b/src/corelib/serialization/qcborvalue.h index f9ade611bba..58013130b84 100644 --- a/src/corelib/serialization/qcborvalue.h +++ b/src/corelib/serialization/qcborvalue.h @@ -368,22 +368,6 @@ public: int compare(const QCborValue &other) const { return concrete().compare(other); } -#if 0 && __has_include() - std::strong_ordering operator<=>(const QCborValue &other) const - { - int c = compare(other); - if (c > 0) return std::strong_ordering::greater; - if (c == 0) return std::strong_ordering::equivalent; - return std::strong_ordering::less; - } -#else - bool operator==(const QCborValue &other) const - { return compare(other) == 0; } - bool operator!=(const QCborValue &other) const - { return !(*this == other); } - bool operator<(const QCborValue &other) const - { return compare(other) < 0; } -#endif QVariant toVariant() const { return concrete().toVariant(); } inline QJsonValue toJsonValue() const; // in qjsonvalue.h @@ -405,7 +389,24 @@ protected: friend class QCborContainerPrivate; QCborValue concrete() const noexcept { return concrete(*this); } - + friend Q_CORE_EXPORT bool comparesEqual(const QCborValueConstRef &lhs, + const QCborValueConstRef &rhs) noexcept; + friend Qt::strong_ordering compareThreeWay(const QCborValueConstRef &lhs, + const QCborValueConstRef &rhs) noexcept + { + int c = lhs.compare(rhs.concrete()); + return Qt::compareThreeWay(c, 0); + } + Q_DECLARE_STRONGLY_ORDERED(QCborValueConstRef) + friend Q_CORE_EXPORT bool comparesEqual(const QCborValueConstRef &lhs, + const QCborValue &rhs) noexcept; + friend Qt::strong_ordering compareThreeWay(const QCborValueConstRef &lhs, + const QCborValue &rhs) noexcept + { + int c = lhs.compare(rhs); + return Qt::compareThreeWay(c, 0); + } + Q_DECLARE_STRONGLY_ORDERED(QCborValueConstRef, QCborValue) static Q_CORE_EXPORT QCborValue concrete(QCborValueConstRef that) noexcept; static Q_CORE_EXPORT QCborValue::Type concreteType(QCborValueConstRef that) noexcept Q_DECL_PURE_FUNCTION; static Q_CORE_EXPORT bool @@ -523,19 +524,11 @@ public: int compare(const QCborValue &other) const { return concrete().compare(other); } -#if 0 && __has_include() - std::strong_ordering operator<=>(const QCborValue &other) const - { - int c = compare(other); - if (c > 0) return std::strong_ordering::greater; - if (c == 0) return std::strong_ordering::equivalent; - return std::strong_ordering::less; - } -#else +#if QT_CORE_REMOVED_SINCE(6, 8) bool operator==(const QCborValue &other) const { return compare(other) == 0; } bool operator!=(const QCborValue &other) const - { return !(*this == other); } + { return !operator==(other); } bool operator<(const QCborValue &other) const { return compare(other) < 0; } #endif diff --git a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp index 7a49f015382..960d37e9dee 100644 --- a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp +++ b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp @@ -27,7 +27,7 @@ private slots: void tagged(); void extendedTypes_data(); void extendedTypes(); - void compareCompiles() { QTestPrivate::testAllComparisonOperatorsCompile(); } + void compareCompiles(); void copyCompare_data() { basics_data(); } void copyCompare(); @@ -79,6 +79,8 @@ private slots: void mapNested(); void sorting(); + void comparison_data(); + void comparison(); void toCbor_data(); void toCbor(); @@ -446,6 +448,16 @@ void tst_QCborValue::extendedTypes_data() << QCborValue(uuid.toRfc4122() + "\1\2\3\4") << QCborValue(uuid.toRfc4122()); } +void tst_QCborValue::compareCompiles() +{ + QTestPrivate::testAllComparisonOperatorsCompile(); + QTestPrivate::testAllComparisonOperatorsCompile(); + QTestPrivate::testAllComparisonOperatorsCompile(); + QTestPrivate::testAllComparisonOperatorsCompile(); + QTestPrivate::testAllComparisonOperatorsCompile(); + QTestPrivate::testAllComparisonOperatorsCompile(); +} + void tst_QCborValue::extendedTypes() { QFETCH(QCborValue, extended); @@ -1110,8 +1122,7 @@ void tst_QCborValue::mapMutation() QVERIFY(v.isTrue()); QCOMPARE(m, QCborMap({{42, true}})); QVERIFY(m.begin()->isTrue()); - QVERIFY(m.begin().value() == v); - QVERIFY(v == m.begin().value()); + QT_TEST_EQUALITY_OPS(m.begin().value(), v, true); } QVERIFY(m == QCborMap({{42, true}})); @@ -1135,10 +1146,10 @@ void tst_QCborValue::mapMutation() auto end = m.end(); QCOMPARE(end - it, 2); QCOMPARE(it + 2, end); - QCOMPARE(it.key(), QCborValue(42)); - QCOMPARE(it.value(), QCborValue(2.5)); - QCOMPARE((++it).value(), QCborValue(nullptr)); - QCOMPARE(it.key(), QCborValue(nullptr)); + QT_TEST_EQUALITY_OPS(it.key(), QCborValue(42), true); + QT_TEST_EQUALITY_OPS(it.value(), QCborValue(2.5), true); + QT_TEST_EQUALITY_OPS((++it).value(), QCborValue(nullptr), true); + QT_TEST_EQUALITY_OPS(it.key(), QCborValue(nullptr), true); QVERIFY(m2 == m); QVERIFY(m == m2); @@ -1191,11 +1202,13 @@ void tst_QCborValue::mapMutateWithCopies() // see QTBUG-83366 QCborMap map; map[QLatin1String("value")] = "TEST"; + QT_TEST_EQUALITY_OPS(map[QLatin1String("value")], "TEST", true); QCOMPARE(map.size(), 1); QCOMPARE(map.value("value"), "TEST"); QCborValue v = map.value("value"); map[QLatin1String("prop2")] = v; + QT_TEST_EQUALITY_OPS(map[QLatin1String("prop2")], v, true); QCOMPARE(map.size(), 2); QCOMPARE(map.value("value"), "TEST"); QCOMPARE(map.value("prop2"), "TEST"); @@ -1209,6 +1222,7 @@ void tst_QCborValue::mapMutateWithCopies() // same as previous, but this is a QJsonValueRef QCborValueRef rv = map[QLatin1String("prop2")]; rv = map[QLatin1String("value")]; + QT_TEST_EQUALITY_OPS(map[QLatin1String("value")], rv, true); QCOMPARE(map.size(), 2); QCOMPARE(map.value("value"), "TEST"); QCOMPARE(map.value("prop2"), "TEST"); @@ -1223,6 +1237,7 @@ void tst_QCborValue::mapMutateWithCopies() // after we create the source QCborValueRef QCborValueRef rv = map[QLatin1String("value")]; map[QLatin1String("prop2")] = rv; + QT_TEST_EQUALITY_OPS(map[QLatin1String("prop2")], rv, true); QCOMPARE(map.size(), 2); QCOMPARE(map.value("value"), "TEST"); QCOMPARE(map.value("prop2"), "TEST"); @@ -3068,6 +3083,61 @@ void tst_QCborValue::testlibFormatting() QCOMPARE(actual, expected); } +void tst_QCborValue::comparison_data() +{ + QTest::addColumn("lhs"); + QTest::addColumn("rhs"); + QTest::addColumn("expectedOrdering"); + + auto addRow = [](QCborValue lhs, QCborValue rhs, Qt::strong_ordering order) { + QTest::addRow("%s-cmp-%s", qPrintable(lhs.toDiagnosticNotation()), + qPrintable(rhs.toDiagnosticNotation())) + << lhs << rhs << order; + }; + // typical, sorts as expected + addRow(0, 0, Qt::strong_ordering::equivalent); + addRow(1, 0, Qt::strong_ordering::greater); + addRow(0, 1, Qt::strong_ordering::less); + addRow(10.0, 10.0, Qt::strong_ordering::equivalent); + addRow(10.5, 10.8, Qt::strong_ordering::less); + addRow(-10.5, -10.8, Qt::strong_ordering::less); + addRow("Qt","Qt", Qt::strong_ordering::equivalent); + addRow("qt","Qt", Qt::strong_ordering::greater); + + // atypical gotchas + addRow(0, -1, Qt::strong_ordering::less); + addRow(10, 10.0, Qt::strong_ordering::less); + addRow(0, "Qt", Qt::strong_ordering::less); + +} + +void tst_QCborValue::comparison() +{ + QFETCH(QCborValue, lhs); + QFETCH(QCborValue, rhs); + QFETCH(Qt::strong_ordering, expectedOrdering); + + QCborArray array{lhs, rhs}; + + QCborValueConstRef lhsCRef = array.constBegin()[0]; + QCborValueConstRef rhsCRef = array.constBegin()[1]; + QCborValueRef lhsRef = array[0]; + QCborValueRef rhsRef = array[1]; + + // QCborValue vs QCborValue + QT_TEST_ALL_COMPARISON_OPS(lhs, rhs, expectedOrdering); + // QCborValueConstRef vs QCborValueConstRef + QT_TEST_ALL_COMPARISON_OPS(lhsCRef, rhsCRef, expectedOrdering); + // QCborValueRef vs QCborValueRef + QT_TEST_ALL_COMPARISON_OPS(lhsRef, rhsRef, expectedOrdering); + // QCborValue vs QCborValueConstRef (and reverse) + QT_TEST_ALL_COMPARISON_OPS(lhs, rhsCRef, expectedOrdering); + // QCborValue vs QCborValueRef (and reverse) + QT_TEST_ALL_COMPARISON_OPS(lhs, rhsRef, expectedOrdering); + // QCborValueConstRef vs QCborValueRef (and reverse) + QT_TEST_ALL_COMPARISON_OPS(lhsCRef, rhsRef, expectedOrdering); +} + QTEST_MAIN(tst_QCborValue) #include "tst_qcborvalue.moc"