summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2017-03-17 11:07:30 +0100
committerMarc Mutz <marc.mutz@kdab.com>2017-03-17 20:28:32 +0000
commit5c724a6087b0a647e8241d35f0d44bce08e35281 (patch)
tree79a2c5cfe795303f1e2fb68135a7bf689cec39d3
parent4ee74257940e2ed21b653b986ad02a746e8438a6 (diff)
QChar: fix ambiguous comparisons with 0, '\0', ... for good
Commit e0ea0f6178c9dbee2a8c888fde84ad1cd9670c6b optimized QChar <-> QString(Ref) comparisons by adding more overloads to avoid creating QStrings from QChars just to compare them. But these new overloads made existing comparisons to QChar ambiguous. This was known at the time for QChar/int comparisons. It has since turned out that also comparing to '\0' is ambiguous, ie. not comparing to int or char per se is ambiguous, but comparing to nullptr constants is, because QString(const char*) is just as good a candidate as QChar(char)/QChar(int). Since we allow QString/QChar comparisons, it seems logical to solve the problem by adding QChar<->nullptr overloads. [ChangeLog][QtCore][QChar] Disambiguated comparisons with nullptr constants such as '\0', which 5.8.0 broke. As a consequence, QChar<->int comparisons are no longer deprecated, as this was a failed attempt at fixing the ambiguity. Change-Id: I680dd509c2286e96894e13078899dbe3b2dd83bc Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/tools/qchar.h26
-rw-r--r--tests/auto/corelib/tools/qchar/tst_qchar.cpp61
2 files changed, 55 insertions, 32 deletions
diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h
index a83e5e6f98..81ef67d116 100644
--- a/src/corelib/tools/qchar.h
+++ b/src/corelib/tools/qchar.h
@@ -578,17 +578,21 @@ Q_DECL_CONSTEXPR inline bool operator>=(QChar c1, QChar c2) Q_DECL_NOTHROW { ret
Q_DECL_CONSTEXPR inline bool operator> (QChar c1, QChar c2) Q_DECL_NOTHROW { return operator< (c2, c1); }
Q_DECL_CONSTEXPR inline bool operator<=(QChar c1, QChar c2) Q_DECL_NOTHROW { return !operator< (c2, c1); }
-// disambiguate QChar == int (but only that, so constrain template to exactly 'int'):
-template <typename T>
-Q_DECL_DEPRECATED_X("don't compare ints to QChars, compare them to QChar::unicode() instead")
-Q_DECL_CONSTEXPR inline
-typename std::enable_if<std::is_same<typename std::remove_cv<T>::type, int>::value, bool>::type
-operator==(QChar lhs, T rhs) Q_DECL_NOEXCEPT { return lhs == QChar(rhs); }
-template <typename T>
-Q_DECL_DEPRECATED_X("don't compare ints to QChars, compare them to QChar::unicode() instead")
-Q_DECL_CONSTEXPR inline
-typename std::enable_if<std::is_same<typename std::remove_cv<T>::type, int>::value, bool>::type
-operator!=(QChar lhs, T rhs) Q_DECL_NOEXCEPT { return lhs != QChar(rhs); }
+
+Q_DECL_CONSTEXPR inline bool operator==(QChar lhs, std::nullptr_t) Q_DECL_NOTHROW { return lhs.isNull(); }
+Q_DECL_CONSTEXPR inline bool operator< (QChar, std::nullptr_t) Q_DECL_NOTHROW { return false; }
+Q_DECL_CONSTEXPR inline bool operator==(std::nullptr_t, QChar rhs) Q_DECL_NOTHROW { return rhs.isNull(); }
+Q_DECL_CONSTEXPR inline bool operator< (std::nullptr_t, QChar rhs) Q_DECL_NOTHROW { return !rhs.isNull(); }
+
+Q_DECL_CONSTEXPR inline bool operator!=(QChar lhs, std::nullptr_t) Q_DECL_NOTHROW { return !operator==(lhs, nullptr); }
+Q_DECL_CONSTEXPR inline bool operator>=(QChar lhs, std::nullptr_t) Q_DECL_NOTHROW { return !operator< (lhs, nullptr); }
+Q_DECL_CONSTEXPR inline bool operator> (QChar lhs, std::nullptr_t) Q_DECL_NOTHROW { return operator< (nullptr, lhs); }
+Q_DECL_CONSTEXPR inline bool operator<=(QChar lhs, std::nullptr_t) Q_DECL_NOTHROW { return !operator< (nullptr, lhs); }
+
+Q_DECL_CONSTEXPR inline bool operator!=(std::nullptr_t, QChar rhs) Q_DECL_NOTHROW { return !operator==(nullptr, rhs); }
+Q_DECL_CONSTEXPR inline bool operator>=(std::nullptr_t, QChar rhs) Q_DECL_NOTHROW { return !operator< (nullptr, rhs); }
+Q_DECL_CONSTEXPR inline bool operator> (std::nullptr_t, QChar rhs) Q_DECL_NOTHROW { return operator< (rhs, nullptr); }
+Q_DECL_CONSTEXPR inline bool operator<=(std::nullptr_t, QChar rhs) Q_DECL_NOTHROW { return !operator< (rhs, nullptr); }
#ifndef QT_NO_DATASTREAM
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, QChar);
diff --git a/tests/auto/corelib/tools/qchar/tst_qchar.cpp b/tests/auto/corelib/tools/qchar/tst_qchar.cpp
index fb436b67d6..b42be94da3 100644
--- a/tests/auto/corelib/tools/qchar/tst_qchar.cpp
+++ b/tests/auto/corelib/tools/qchar/tst_qchar.cpp
@@ -36,7 +36,7 @@ class tst_QChar : public QObject
{
Q_OBJECT
private slots:
- void operator_eqeq_int();
+ void operator_eqeq_null();
void operators_data();
void operators();
void toUpper();
@@ -72,35 +72,54 @@ private slots:
void unicodeVersion();
};
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
-
-void tst_QChar::operator_eqeq_int()
+void tst_QChar::operator_eqeq_null()
{
{
const QChar ch = QLatin1Char(' ');
- QVERIFY(ch != 0);
- QVERIFY(!(ch == 0));
-
- QVERIFY(ch == 0x20);
- QVERIFY(!(ch != 0x20));
- QVERIFY(0x20 == ch);
- QVERIFY(!(0x20 != ch));
+#define CHECK(NUL) \
+ do { \
+ QVERIFY(!(ch == NUL)); \
+ QVERIFY( ch != NUL ); \
+ QVERIFY(!(ch < NUL)); \
+ QVERIFY( ch > NUL ); \
+ QVERIFY(!(ch <= NUL)); \
+ QVERIFY( ch >= NUL ); \
+ QVERIFY(!(NUL == ch )); \
+ QVERIFY( NUL != ch ); \
+ QVERIFY( NUL < ch ); \
+ QVERIFY(!(NUL > ch )); \
+ QVERIFY( NUL <= ch ); \
+ QVERIFY(!(NUL >= ch )); \
+ } while (0)
+
+ CHECK(0);
+ CHECK('\0');
+#undef CHECK
}
{
const QChar ch = QLatin1Char('\0');
- QVERIFY(ch == 0);
- QVERIFY(!(ch != 0));
-
- QVERIFY(ch != 0x20);
- QVERIFY(!(ch == 0x20));
- QVERIFY(0x20 != ch);
- QVERIFY(!(0x20 == ch));
+#define CHECK(NUL) \
+ do { \
+ QVERIFY( ch == NUL ); \
+ QVERIFY(!(ch != NUL)); \
+ QVERIFY(!(ch < NUL)); \
+ QVERIFY(!(ch > NUL)); \
+ QVERIFY( ch <= NUL ); \
+ QVERIFY( ch >= NUL ); \
+ QVERIFY( NUL == ch ); \
+ QVERIFY(!(NUL != ch )); \
+ QVERIFY(!(NUL < ch )); \
+ QVERIFY(!(NUL > ch )); \
+ QVERIFY( NUL <= ch ); \
+ QVERIFY( NUL >= ch ); \
+ } while (0)
+
+ CHECK(0);
+ CHECK('\0');
+#undef CHECK
}
}
-QT_WARNING_POP
-
void tst_QChar::operators_data()
{
QTest::addColumn<QChar>("lhs");