summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/tools/qtaggedpointer.h23
-rw-r--r--tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp42
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: