summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Solovev <ivan.solovev@qt.io>2024-02-16 18:37:14 +0100
committerIvan Solovev <ivan.solovev@qt.io>2024-03-02 00:12:53 +0100
commit755581e2e78f017f2c783a637ddb2ab9108b083b (patch)
treec5809720649cb37c3263632c7e9ae5911789a4bf
parent6d08db86660139176df653b02d4168c9372c750e (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.cpp78
-rw-r--r--src/corelib/text/qstring.h101
-rw-r--r--tests/auto/corelib/text/qstring/CMakeLists.txt1
-rw-r--r--tests/auto/corelib/text/qstring/tst_qstring.cpp51
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;