summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qtaggedpointer.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/tools/qtaggedpointer.h')
-rw-r--r--src/corelib/tools/qtaggedpointer.h37
1 files changed, 29 insertions, 8 deletions
diff --git a/src/corelib/tools/qtaggedpointer.h b/src/corelib/tools/qtaggedpointer.h
index 504645993a..6c467d59f8 100644
--- a/src/corelib/tools/qtaggedpointer.h
+++ b/src/corelib/tools/qtaggedpointer.h
@@ -21,7 +21,7 @@ namespace QtPrivate {
static_assert((alignment & (alignment - 1)) == 0,
"Alignment of template parameter must be power of two");
- static constexpr quint8 tagBits = QtPrivate::qConstexprCountTrailingZeroBits(alignment);
+ static constexpr quint8 tagBits = quint8{QtPrivate::qConstexprCountTrailingZeroBits(alignment)};
static_assert(tagBits > 0,
"Alignment of template parameter does not allow any tags");
@@ -43,10 +43,10 @@ public:
static constexpr quintptr tagMask() { return QtPrivate::TagInfo<T>::alignment - 1; }
static constexpr quintptr pointerMask() { return ~tagMask(); }
- constexpr QTaggedPointer() noexcept : d(0) {}
- constexpr QTaggedPointer(std::nullptr_t) noexcept : QTaggedPointer() {}
+ Q_NODISCARD_CTOR constexpr QTaggedPointer() noexcept : d(0) {}
+ Q_NODISCARD_CTOR constexpr QTaggedPointer(std::nullptr_t) noexcept : QTaggedPointer() {}
- explicit QTaggedPointer(T *pointer, Tag tag = Tag()) noexcept
+ Q_NODISCARD_CTOR explicit QTaggedPointer(T *pointer, Tag tag = Tag()) noexcept
: d(quintptr(pointer) | quintptr(tag))
{
static_assert(sizeof(Type*) == sizeof(QTaggedPointer));
@@ -72,12 +72,31 @@ 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
{
- d = reinterpret_cast<quintptr>(other) | (d & tagMask());
+ 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>(static_cast<T *>(nullptr)) | (d & tagMask());
+ return *this;
+ }
+#endif
+
static constexpr Tag maximumTag() noexcept
{
return TagType(typename QtPrivate::TagInfo<T>::TagType(tagMask()));
@@ -85,8 +104,10 @@ public:
void setTag(Tag tag)
{
- Q_ASSERT_X((static_cast<typename QtPrivate::TagInfo<T>::TagType>(tag) & pointerMask()) == 0,
- "QTaggedPointer<T, Tag>::setTag", "Tag is larger than allowed by number of available tag bits");
+ Q_ASSERT_X(
+ (static_cast<quintptr>(tag) & pointerMask()) == 0,
+ "QTaggedPointer<T, Tag>::setTag",
+ "Tag is larger than allowed by number of available tag bits");
d = (d & pointerMask()) | static_cast<quintptr>(tag);
}