diff options
author | Ivan Solovev <ivan.solovev@qt.io> | 2024-02-16 18:37:14 +0100 |
---|---|---|
committer | Ivan Solovev <ivan.solovev@qt.io> | 2024-03-02 00:12:53 +0100 |
commit | 755581e2e78f017f2c783a637ddb2ab9108b083b (patch) | |
tree | c5809720649cb37c3263632c7e9ae5911789a4bf | |
parent | 6d08db86660139176df653b02d4168c9372c750e (diff) |
QString: use comparison helper macros - trivial changes [1/3]
Replace the hidden friend relational operators with hidden friend
helper functions and comparison helper macros.
Provide more unit-tests for the updated types.
This enables operator<=> in C++20 builds.
Task-number: QTBUG-117661
Change-Id: I17329cd6422f272a435fc1da241203581eef7fbb
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r-- | src/corelib/text/qstring.cpp | 78 | ||||
-rw-r--r-- | src/corelib/text/qstring.h | 101 | ||||
-rw-r--r-- | tests/auto/corelib/text/qstring/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/auto/corelib/text/qstring/tst_qstring.cpp | 51 |
4 files changed, 127 insertions, 104 deletions
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index 9637a4b337..6ae367a358 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -1702,6 +1702,10 @@ void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *whe \ingroup shared \ingroup string-processing + \compares strong + \compareswith strong QChar QLatin1StringView {const char16_t *} + \endcompareswith + QString stores a string of 16-bit \l{QChar}s, where each QChar corresponds to one UTF-16 code unit. (Unicode characters with code values above 65535 are stored using surrogate pairs, @@ -4052,10 +4056,10 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity } /*! - \fn bool QString::operator==(const QString &s1, const QString &s2) + \fn bool QString::operator==(const QString &lhs, const QString &rhs) \overload operator==() - Returns \c true if string \a s1 is equal to string \a s2; otherwise + Returns \c true if string \a lhs is equal to string \a rhs; otherwise returns \c false. \include qstring.cpp compare-isNull-vs-isEmpty @@ -4064,20 +4068,20 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity */ /*! - \fn bool QString::operator==(const QString &s1, QLatin1StringView s2) + \fn bool QString::operator==(const QString &lhs, const QLatin1StringView &rhs) \overload operator==() - Returns \c true if \a s1 is equal to \a s2; otherwise + Returns \c true if \a lhs is equal to \a rhs; otherwise returns \c false. */ /*! - \fn bool QString::operator==(QLatin1StringView s1, const QString &s2) + \fn bool QString::operator==(const QLatin1StringView &lhs, const QString &rhs) \overload operator==() - Returns \c true if \a s1 is equal to \a s2; otherwise + Returns \c true if \a lhs is equal to \a rhs; otherwise returns \c false. */ @@ -4111,31 +4115,31 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity */ /*! - \fn bool QString::operator<(const QString &s1, const QString &s2) + \fn bool QString::operator<(const QString &lhs, const QString &rhs) \overload operator<() - Returns \c true if string \a s1 is lexically less than string - \a s2; otherwise returns \c false. + Returns \c true if string \a lhs is lexically less than string + \a rhs; otherwise returns \c false. \sa {Comparing Strings} */ /*! - \fn bool QString::operator<(const QString &s1, QLatin1StringView s2) + \fn bool QString::operator<(const QString &lhs, const QLatin1StringView &rhs) \overload operator<() - Returns \c true if \a s1 is lexically less than \a s2; + Returns \c true if \a lhs is lexically less than \a rhs; otherwise returns \c false. */ /*! - \fn bool QString::operator<(QLatin1StringView s1, const QString &s2) + \fn bool QString::operator<(const QLatin1StringView &lhs, const QString &rhs) \overload operator<() - Returns \c true if \a s1 is lexically less than \a s2; + Returns \c true if \a lhs is lexically less than \a rhs; otherwise returns \c false. */ @@ -4169,29 +4173,29 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity go through QObject::tr(), for example. */ -/*! \fn bool QString::operator<=(const QString &s1, const QString &s2) +/*! \fn bool QString::operator<=(const QString &lhs, const QString &rhs) - Returns \c true if string \a s1 is lexically less than or equal to - string \a s2; otherwise returns \c false. + Returns \c true if string \a lhs is lexically less than or equal to + string \a rhs; otherwise returns \c false. \sa {Comparing Strings} */ /*! - \fn bool QString::operator<=(const QString &s1, QLatin1StringView s2) + \fn bool QString::operator<=(const QString &lhs, const QLatin1StringView &rhs) \overload operator<=() - Returns \c true if \a s1 is lexically less than or equal to \a s2; + Returns \c true if \a lhs is lexically less than or equal to \a rhs; otherwise returns \c false. */ /*! - \fn bool QString::operator<=(QLatin1StringView s1, const QString &s2) + \fn bool QString::operator<=(const QLatin1StringView &lhs, const QString &rhs) \overload operator<=() - Returns \c true if \a s1 is lexically less than or equal to \a s2; + Returns \c true if \a lhs is lexically less than or equal to \a rhs; otherwise returns \c false. */ @@ -4222,29 +4226,29 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity go through QObject::tr(), for example. */ -/*! \fn bool QString::operator>(const QString &s1, const QString &s2) +/*! \fn bool QString::operator>(const QString &lhs, const QString &rhs) - Returns \c true if string \a s1 is lexically greater than string \a s2; + Returns \c true if string \a lhs is lexically greater than string \a rhs; otherwise returns \c false. \sa {Comparing Strings} */ /*! - \fn bool QString::operator>(const QString &s1, QLatin1StringView s2) + \fn bool QString::operator>(const QString &lhs, const QLatin1StringView &rhs) \overload operator>() - Returns \c true if \a s1 is lexically greater than \a s2; + Returns \c true if \a lhs is lexically greater than \a rhs; otherwise returns \c false. */ /*! - \fn bool QString::operator>(QLatin1StringView s1, const QString &s2) + \fn bool QString::operator>(const QLatin1StringView &lhs, const QString &rhs) \overload operator>() - Returns \c true if \a s1 is lexically greater than \a s2; + Returns \c true if \a lhs is lexically greater than \a rhs; otherwise returns \c false. */ @@ -4275,29 +4279,29 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity for example. */ -/*! \fn bool QString::operator>=(const QString &s1, const QString &s2) +/*! \fn bool QString::operator>=(const QString &lhs, const QString &rhs) - Returns \c true if string \a s1 is lexically greater than or equal to - string \a s2; otherwise returns \c false. + Returns \c true if string \a lhs is lexically greater than or equal to + string \a rhs; otherwise returns \c false. \sa {Comparing Strings} */ /*! - \fn bool QString::operator>=(const QString &s1, QLatin1StringView s2) + \fn bool QString::operator>=(const QString &lhs, const QLatin1StringView &rhs) \overload operator>=() - Returns \c true if \a s1 is lexically greater than or equal to \a s2; + Returns \c true if \a lhs is lexically greater than or equal to \a rhs; otherwise returns \c false. */ /*! - \fn bool QString::operator>=(QLatin1StringView s1, const QString &s2) + \fn bool QString::operator>=(const QLatin1StringView &lhs, const QString &rhs) \overload operator>=() - Returns \c true if \a s1 is lexically greater than or equal to \a s2; + Returns \c true if \a lhs is lexically greater than or equal to \a rhs; otherwise returns \c false. */ @@ -4328,17 +4332,17 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity for example. */ -/*! \fn bool QString::operator!=(const QString &s1, const QString &s2) +/*! \fn bool QString::operator!=(const QString &lhs, const QString &rhs) - Returns \c true if string \a s1 is not equal to string \a s2; + Returns \c true if string \a lhs is not equal to string \a rhs; otherwise returns \c false. \sa {Comparing Strings} */ -/*! \fn bool QString::operator!=(const QString &s1, QLatin1StringView s2) +/*! \fn bool QString::operator!=(const QString &lhs, const QLatin1StringView &rhs) - Returns \c true if string \a s1 is not equal to string \a s2. + Returns \c true if string \a lhs is not equal to string \a rhs. Otherwise returns \c false. \overload operator!=() diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h index 9b3434a04b..6c64f6356a 100644 --- a/src/corelib/text/qstring.h +++ b/src/corelib/text/qstring.h @@ -12,6 +12,7 @@ #endif #include <QtCore/qchar.h> +#include <QtCore/qcompare.h> #include <QtCore/qbytearray.h> #include <QtCore/qbytearrayview.h> #include <QtCore/qarraydata.h> @@ -760,78 +761,44 @@ public: static QString number(qulonglong, int base=10); static QString number(double, char format='g', int precision=6); - friend bool operator==(const QString &s1, const QString &s2) noexcept - { return (s1.size() == s2.size()) && QtPrivate::equalStrings(s1, s2); } - friend bool operator< (const QString &s1, const QString &s2) noexcept - { return QtPrivate::compareStrings(s1, s2, Qt::CaseSensitive) < 0; } - friend bool operator> (const QString &s1, const QString &s2) noexcept { return s2 < s1; } - friend bool operator!=(const QString &s1, const QString &s2) noexcept { return !(s1 == s2); } - friend bool operator<=(const QString &s1, const QString &s2) noexcept { return !(s1 > s2); } - friend bool operator>=(const QString &s1, const QString &s2) noexcept { return !(s1 < s2); } - - friend bool operator==(const QString &s1, QLatin1StringView s2) noexcept + friend bool comparesEqual(const QString &s1, const QString &s2) noexcept + { return comparesEqual(QStringView(s1), QStringView(s2)); } + friend Qt::strong_ordering compareThreeWay(const QString &s1, const QString &s2) noexcept + { return compareThreeWay(QStringView(s1), QStringView(s2)); } + Q_DECLARE_STRONGLY_ORDERED(QString) + + friend bool comparesEqual(const QString &s1, QLatin1StringView s2) noexcept { return (s1.size() == s2.size()) && QtPrivate::equalStrings(s1, s2); } - friend bool operator< (const QString &s1, QLatin1StringView s2) noexcept - { return QtPrivate::compareStrings(s1, s2, Qt::CaseSensitive) < 0; } - friend bool operator> (const QString &s1, QLatin1StringView s2) noexcept - { return QtPrivate::compareStrings(s1, s2, Qt::CaseSensitive) > 0; } - friend bool operator!=(const QString &s1, QLatin1StringView s2) noexcept { return !(s1 == s2); } - friend bool operator<=(const QString &s1, QLatin1StringView s2) noexcept { return !(s1 > s2); } - friend bool operator>=(const QString &s1, QLatin1StringView s2) noexcept { return !(s1 < s2); } - - friend bool operator==(QLatin1StringView s1, const QString &s2) noexcept { return s2 == s1; } - friend bool operator< (QLatin1StringView s1, const QString &s2) noexcept { return s2 > s1; } - friend bool operator> (QLatin1StringView s1, const QString &s2) noexcept { return s2 < s1; } - friend bool operator!=(QLatin1StringView s1, const QString &s2) noexcept { return s2 != s1; } - friend bool operator<=(QLatin1StringView s1, const QString &s2) noexcept { return s2 >= s1; } - friend bool operator>=(QLatin1StringView s1, const QString &s2) noexcept { return s2 <= s1; } + friend Qt::strong_ordering + compareThreeWay(const QString &s1, QLatin1StringView s2) noexcept + { + const int res = QtPrivate::compareStrings(s1, s2, Qt::CaseSensitive); + return Qt::compareThreeWay(res, 0); + } + Q_DECLARE_STRONGLY_ORDERED(QString, QLatin1StringView) // Check isEmpty() instead of isNull() for backwards compatibility. - friend bool operator==(const QString &s1, std::nullptr_t) noexcept { return s1.isEmpty(); } - friend bool operator!=(const QString &s1, std::nullptr_t) noexcept { return !s1.isEmpty(); } - friend bool operator< (const QString & , std::nullptr_t) noexcept { return false; } - friend bool operator> (const QString &s1, std::nullptr_t) noexcept { return !s1.isEmpty(); } - friend bool operator<=(const QString &s1, std::nullptr_t) noexcept { return s1.isEmpty(); } - friend bool operator>=(const QString & , std::nullptr_t) noexcept { return true; } - friend bool operator==(std::nullptr_t, const QString &s2) noexcept { return s2 == nullptr; } - friend bool operator!=(std::nullptr_t, const QString &s2) noexcept { return s2 != nullptr; } - friend bool operator< (std::nullptr_t, const QString &s2) noexcept { return s2 > nullptr; } - friend bool operator> (std::nullptr_t, const QString &s2) noexcept { return s2 < nullptr; } - friend bool operator<=(std::nullptr_t, const QString &s2) noexcept { return s2 >= nullptr; } - friend bool operator>=(std::nullptr_t, const QString &s2) noexcept { return s2 <= nullptr; } - - friend bool operator==(const QString &s1, const char16_t *s2) noexcept { return s1 == QStringView(s2); } - friend bool operator!=(const QString &s1, const char16_t *s2) noexcept { return s1 != QStringView(s2); } - friend bool operator< (const QString &s1, const char16_t *s2) noexcept { return s1 < QStringView(s2); } - friend bool operator> (const QString &s1, const char16_t *s2) noexcept { return s1 > QStringView(s2); } - friend bool operator<=(const QString &s1, const char16_t *s2) noexcept { return s1 <= QStringView(s2); } - friend bool operator>=(const QString &s1, const char16_t *s2) noexcept { return s1 >= QStringView(s2); } - - friend bool operator==(const char16_t *s1, const QString &s2) noexcept { return s2 == s1; } - friend bool operator!=(const char16_t *s1, const QString &s2) noexcept { return s2 != s1; } - friend bool operator< (const char16_t *s1, const QString &s2) noexcept { return s2 > s1; } - friend bool operator> (const char16_t *s1, const QString &s2) noexcept { return s2 < s1; } - friend bool operator<=(const char16_t *s1, const QString &s2) noexcept { return s2 >= s1; } - friend bool operator>=(const char16_t *s1, const QString &s2) noexcept { return s2 <= s1; } + friend bool comparesEqual(const QString &s1, std::nullptr_t) noexcept + { return s1.isEmpty(); } + friend Qt::strong_ordering compareThreeWay(const QString &s1, std::nullptr_t) noexcept + { return s1.isEmpty() ? Qt::strong_ordering::equivalent : Qt::strong_ordering::greater; } + Q_DECLARE_STRONGLY_ORDERED(QString, std::nullptr_t) + + friend bool comparesEqual(const QString &s1, const char16_t *s2) noexcept + { return comparesEqual(s1, QStringView(s2)); } + friend Qt::strong_ordering compareThreeWay(const QString &s1, const char16_t *s2) noexcept + { return compareThreeWay(s1, QStringView(s2)); } + Q_DECLARE_STRONGLY_ORDERED(QString, const char16_t *) // QChar <> QString - friend inline bool operator==(QChar lhs, const QString &rhs) noexcept - { return rhs.size() == 1 && lhs == rhs.front(); } - friend inline bool operator< (QChar lhs, const QString &rhs) noexcept - { return compare_helper(&lhs, 1, rhs.data(), rhs.size()) < 0; } - friend inline bool operator> (QChar lhs, const QString &rhs) noexcept - { return compare_helper(&lhs, 1, rhs.data(), rhs.size()) > 0; } - - friend inline bool operator!=(QChar lhs, const QString &rhs) noexcept { return !(lhs == rhs); } - friend inline bool operator<=(QChar lhs, const QString &rhs) noexcept { return !(lhs > rhs); } - friend inline bool operator>=(QChar lhs, const QString &rhs) noexcept { return !(lhs < rhs); } - - friend inline bool operator==(const QString &lhs, QChar rhs) noexcept { return rhs == lhs; } - friend inline bool operator!=(const QString &lhs, QChar rhs) noexcept { return !(rhs == lhs); } - friend inline bool operator< (const QString &lhs, QChar rhs) noexcept { return rhs > lhs; } - friend inline bool operator> (const QString &lhs, QChar rhs) noexcept { return rhs < lhs; } - friend inline bool operator<=(const QString &lhs, QChar rhs) noexcept { return !(rhs < lhs); } - friend inline bool operator>=(const QString &lhs, QChar rhs) noexcept { return !(rhs > lhs); } + friend bool comparesEqual(const QString &lhs, QChar rhs) noexcept + { return lhs.size() == 1 && rhs == lhs.front(); } + friend Qt::strong_ordering compareThreeWay(const QString &lhs, QChar rhs) noexcept + { + const int res = compare_helper(lhs.data(), lhs.size(), &rhs, 1); + return Qt::compareThreeWay(res, 0); + } + Q_DECLARE_STRONGLY_ORDERED(QString, QChar) // ASCII compatibility #if defined(QT_RESTRICTED_CAST_FROM_ASCII) diff --git a/tests/auto/corelib/text/qstring/CMakeLists.txt b/tests/auto/corelib/text/qstring/CMakeLists.txt index 93bf582e6b..80917554d2 100644 --- a/tests/auto/corelib/text/qstring/CMakeLists.txt +++ b/tests/auto/corelib/text/qstring/CMakeLists.txt @@ -27,6 +27,7 @@ foreach(test tst_qstring tst_qstring_restricted_ascii tst_qstring_no_cast_from_a ${tst_qstring_extra_sources} LIBRARIES Qt::CorePrivate + Qt::TestPrivate ${tst_qstring_extra_libraries} DEFINES ${tst_qstring_extra_defines} diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp index c888daaa57..6aaa8bc813 100644 --- a/tests/auto/corelib/text/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp @@ -10,6 +10,7 @@ #endif #include <private/qglobal_p.h> // for the icu feature test +#include <QtTest/private/qcomparisontesthelper_p.h> #include <QTest> #include <QString> #include <QStringBuilder> @@ -668,8 +669,11 @@ private slots: void isNan_data(); void isNan(); void nanAndInf(); + void comparisonCompiles(); void compare_data(); void compare(); + void comparisonMacros_data(); + void comparisonMacros(); void resize(); void resizeAfterFromRawData(); void resizeAfterReserve(); @@ -8030,6 +8034,15 @@ void tst_QString::arg_fillChar() QCOMPARE(actual, expected); } +void tst_QString::comparisonCompiles() +{ + QTestPrivate::testAllComparisonOperatorsCompile<QString>(); + QTestPrivate::testAllComparisonOperatorsCompile<QString, std::nullptr_t>(); + QTestPrivate::testAllComparisonOperatorsCompile<QString, QChar>(); + QTestPrivate::testAllComparisonOperatorsCompile<QString, QLatin1StringView>(); + QTestPrivate::testAllComparisonOperatorsCompile<QString, const char16_t *>(); +} + void tst_QString::compare_data() { QTest::addColumn<QString>("s1"); @@ -8219,6 +8232,44 @@ void tst_QString::compare() } } +void tst_QString::comparisonMacros_data() +{ + compare_data(); +} + +void tst_QString::comparisonMacros() +{ + QFETCH(const QString, s1); + QFETCH(const QString, s2); + QFETCH(int, csr); + + const Qt::strong_ordering expectedOrdering = [&csr] { + if (csr > 0) + return Qt::strong_ordering::greater; + else if (csr < 0) + return Qt::strong_ordering::less; + return Qt::strong_ordering::equal; + }(); + + QT_TEST_ALL_COMPARISON_OPS(s1, s2, expectedOrdering); + + if (!s2.contains(QChar(u'\0'))) { + const char16_t *utfData = reinterpret_cast<const char16_t*>(s2.constData()); + QT_TEST_ALL_COMPARISON_OPS(s1, utfData, expectedOrdering); + } + + if (s2.size() == 1) { + const QChar ch = s2.front(); + QT_TEST_ALL_COMPARISON_OPS(s1, ch, expectedOrdering); + } + + if (isLatin(s2)) { + QByteArray ba = s2.toLatin1(); + const QLatin1StringView l1s2{ba}; + QT_TEST_ALL_COMPARISON_OPS(s1, l1s2, expectedOrdering); + } +} + void tst_QString::resize() { QString s; |