diff options
| -rw-r--r-- | src/corelib/tools/qtaggedpointer.h | 23 | ||||
| -rw-r--r-- | tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp | 42 |
2 files changed, 63 insertions, 2 deletions
diff --git a/src/corelib/tools/qtaggedpointer.h b/src/corelib/tools/qtaggedpointer.h index 504645993a2..a08912c4a57 100644 --- a/src/corelib/tools/qtaggedpointer.h +++ b/src/corelib/tools/qtaggedpointer.h @@ -72,11 +72,30 @@ public: return !isNull(); } - QTaggedPointer &operator=(T *other) noexcept +#ifdef Q_QDOC + QTaggedPointer &operator=(T *other) noexcept; +#else + // Disables the usage of `ptr = {}`, which would go through this operator + // (rather than using the implicitly-generated assignment operator). + // The operators have different semantics: the ones here leave the tag intact, + // the implicitly-generated one overwrites it. + template <typename U, + std::enable_if_t<std::is_convertible_v<U *, T *>, bool> = false> + QTaggedPointer &operator=(U *other) noexcept + { + T *otherT = other; + d = reinterpret_cast<quintptr>(otherT) | (d & tagMask()); + return *this; + } + + template <typename U, + std::enable_if_t<std::is_null_pointer_v<U>, bool> = false> + QTaggedPointer &operator=(U) noexcept { - d = reinterpret_cast<quintptr>(other) | (d & tagMask()); + d = reinterpret_cast<quintptr>(static_cast<T *>(nullptr)) | (d & tagMask()); return *this; } +#endif static constexpr Tag maximumTag() noexcept { diff --git a/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp b/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp index 752bf48d93a..5cb82329d0c 100644 --- a/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp +++ b/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp @@ -11,6 +11,7 @@ class tst_QTaggedPointer : public QObject private Q_SLOTS: void constExpr(); void construction(); + void assignment(); void dereferenceOperator(); void pointerOperator(); void negationOperator(); @@ -80,6 +81,47 @@ void tst_QTaggedPointer::construction() } } +void tst_QTaggedPointer::assignment() +{ + QScopedPointer<int> rawPointer(new int(5)); + QTaggedPointer<int> p(rawPointer.data(), 0x1); + QTaggedPointer<int> p2(rawPointer.data(), 0x2); + + QCOMPARE(p.data(), rawPointer.data()); + QCOMPARE(p.tag(), quintptr(0x1)); + + QCOMPARE(p2.data(), rawPointer.data()); + QCOMPARE(p2.tag(), quintptr(0x2)); + + p = nullptr; + QCOMPARE(p.data(), nullptr); + QCOMPARE(p.tag(), quintptr(0x1)); + + p = rawPointer.data(); + QCOMPARE(p.data(), rawPointer.data()); + QCOMPARE(p.tag(), quintptr(0x1)); + + p = {}; + QCOMPARE(p.data(), nullptr); + QCOMPARE(p.tag(), quintptr(0x0)); + + p = p2; + QCOMPARE(p.data(), rawPointer.data()); + QCOMPARE(p.tag(), quintptr(0x2)); + + p = nullptr; + QCOMPARE(p.data(), nullptr); + QCOMPARE(p.tag(), quintptr(0x2)); + + p = {}; + QCOMPARE(p.data(), nullptr); + QCOMPARE(p.tag(), quintptr(0x0)); + + p = rawPointer.data(); + QCOMPARE(p.data(), rawPointer.data()); + QCOMPARE(p.tag(), quintptr(0x0)); +} + class AbstractClass { public: |
