Skip to content

Commit

Permalink
QTaggedPointer: some API cleanups
Browse files Browse the repository at this point in the history
- don't refer to the class with template arguments in the body of the class
  (incl. one where we got the template args wrong)
- make namespace-level swap a non-member friend
- make default ctor constexpr and non-explicit
  (default ctors should never be explicit)
- make ctor from std::nullptr_t constexpr
- remove op= from std::nullptr (will be handled by op=(T*) anyway)
- pass QTaggedPointer by value (it's a Trivial Type, so can be passed in registers)
- fix missing QTypeInfo for non-default Tag types
- remove unused include limits.h
- make qHash-able (why is the tag ignored?)

Change-Id: Idee1d685ac365c988698a8637fd5df3accfc1396
Reviewed-by: Thiago Macieira <[email protected]>
  • Loading branch information
marc-kdab committed May 15, 2020
1 parent e5683c5 commit 5ffa580
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 31 deletions.
50 changes: 25 additions & 25 deletions src/corelib/tools/qtaggedpointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qalgorithms.h>
#include <QtCore/qmath.h>

#include <limits.h>
#include <QtCore/qtypeinfo.h>

QT_BEGIN_NAMESPACE

Expand Down Expand Up @@ -80,10 +79,13 @@ class QTaggedPointer
static constexpr quintptr tagMask() { return QtPrivate::TagInfo<T>::alignment - 1; }
static constexpr quintptr pointerMask() { return ~tagMask(); }

explicit QTaggedPointer(T *pointer = nullptr, Tag tag = Tag()) noexcept
constexpr QTaggedPointer() noexcept : d(0) {}
constexpr QTaggedPointer(std::nullptr_t) noexcept : QTaggedPointer() {}

explicit QTaggedPointer(T *pointer, Tag tag = Tag()) noexcept
: d(quintptr(pointer))
{
Q_STATIC_ASSERT(sizeof(Type*) == sizeof(QTaggedPointer<Type>));
Q_STATIC_ASSERT(sizeof(Type*) == sizeof(QTaggedPointer));

Q_ASSERT_X((quintptr(pointer) & tagMask()) == 0,
"QTaggedPointer<T, Tag>", "Pointer is not aligned");
Expand All @@ -107,18 +109,12 @@ class QTaggedPointer
return !isNull();
}

QTaggedPointer<T, Tag> &operator=(T *other) noexcept
QTaggedPointer &operator=(T *other) noexcept
{
d = reinterpret_cast<quintptr>(other) | (d & tagMask());
return *this;
}

QTaggedPointer<T, Tag> &operator=(std::nullptr_t) noexcept
{
d &= tagMask();
return *this;
}

static constexpr Tag maximumTag() noexcept
{
return TagType(typename QtPrivate::TagInfo<T>::TagType(tagMask()));
Expand Down Expand Up @@ -147,58 +143,62 @@ class QTaggedPointer
return !data();
}

void swap(QTaggedPointer<T, Tag> &other) noexcept
void swap(QTaggedPointer &other) noexcept
{
qSwap(d, other.d);
}

friend inline bool operator==(const QTaggedPointer<T, Tag> &lhs, const QTaggedPointer<T, Tag> &rhs) noexcept
friend inline bool operator==(QTaggedPointer lhs, QTaggedPointer rhs) noexcept
{
return lhs.data() == rhs.data();
}

friend inline bool operator!=(const QTaggedPointer<T, Tag> &lhs, const QTaggedPointer<T, Tag> &rhs) noexcept
friend inline bool operator!=(QTaggedPointer lhs, QTaggedPointer rhs) noexcept
{
return lhs.data() != rhs.data();
}

friend inline bool operator==(const QTaggedPointer<T, Tag> &lhs, std::nullptr_t) noexcept
friend inline bool operator==(QTaggedPointer lhs, std::nullptr_t) noexcept
{
return lhs.isNull();
}

friend inline bool operator==(std::nullptr_t, const QTaggedPointer<T, Tag> &rhs) noexcept
friend inline bool operator==(std::nullptr_t, QTaggedPointer rhs) noexcept
{
return rhs.isNull();
}

friend inline bool operator!=(const QTaggedPointer<T, Tag> &lhs, std::nullptr_t) noexcept
friend inline bool operator!=(QTaggedPointer lhs, std::nullptr_t) noexcept
{
return !lhs.isNull();
}

friend inline bool operator!=(std::nullptr_t, const QTaggedPointer<T, Tag> &rhs) noexcept
friend inline bool operator!=(std::nullptr_t, QTaggedPointer rhs) noexcept
{
return !rhs.isNull();
}

friend inline bool operator!(const QTaggedPointer<T, Tag> &ptr) noexcept
friend inline bool operator!(QTaggedPointer ptr) noexcept
{
return !ptr.data();
}

friend inline void swap(QTaggedPointer &p1, QTaggedPointer &p2) noexcept
{
p1.swap(p2);
}

protected:
quintptr d;
};

template <typename T>
Q_DECLARE_TYPEINFO_BODY(QTaggedPointer<T>, Q_MOVABLE_TYPE);
template <typename T, typename Tag>
constexpr inline std::size_t qHash(QTaggedPointer<T, Tag> p, std::size_t seed = 0) noexcept
{ return qHash(p.data(), seed); }

template <typename T, typename Tag>
inline void swap(QTaggedPointer<T, Tag> &p1, QTaggedPointer<T, Tag> &p2) noexcept
{
p1.swap(p2);
}
class QTypeInfo<QTaggedPointer<T, Tag>>
: public QTypeInfoMerger<QTaggedPointer<T, Tag>, quintptr> {};

QT_END_NAMESPACE

Expand Down
30 changes: 24 additions & 6 deletions src/corelib/tools/qtaggedpointer.qdoc
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,18 @@
*/


/*!
\fn template <typename T, typename Tag> QTaggedPointer<T, Tag>::QTaggedPointer()

Creates a tagged pointer that contains nullptr and stores no tag.
*/

/*!
\fn template <typename T, typename Tag> QTaggedPointer<T, Tag>::QTaggedPointer(std::nullptr_t)

Creates a tagged pointer that contains nullptr and stores no tag.
*/

/*!
\fn template <typename T, typename Tag> explicit QTaggedPointer<T, Tag>::QTaggedPointer(T *pointer = nullptr, Tag tag = Tag()) noexcept

Expand Down Expand Up @@ -159,7 +171,7 @@
*/

/*!
\fn template <typename T, typename Tag> inline bool operator==(const QTaggedPointer<T, Tag> &lhs, const QTaggedPointer<T, Tag> &rhs) noexcept
\fn template <typename T, typename Tag> inline bool operator==(QTaggedPointer lhs, QTaggedPointer rhs) noexcept
\relates QTaggedPointer

Returns \c true if \a lhs is equal to \a rhs; otherwise returns \c false.
Expand All @@ -168,7 +180,7 @@
*/

/*!
\fn template <typename T, typename Tag> inline bool operator!=(const QTaggedPointer<T, Tag> &lhs, const QTaggedPointer<T, Tag> &rhs) noexcept
\fn template <typename T, typename Tag> inline bool operator!=(QTaggedPointer lhs, QTaggedPointer rhs) noexcept
\relates QTaggedPointer

Returns \c true if \a lhs is not equal to \a rhs; otherwise returns \c false.
Expand All @@ -177,30 +189,36 @@
*/

/*!
\fn template <typename T, typename Tag> inline bool operator==(const QTaggedPointer<T, Tag> &lhs, std::nullptr_t) noexcept
\fn template <typename T, typename Tag> inline bool operator==(QTaggedPointer lhs, std::nullptr_t) noexcept
\relates QTaggedPointer

Returns \c true if \a lhs refers to \c nullptr.
*/

/*!
\fn template <typename T, typename Tag> inline bool operator==(std::nullptr_t, const QTaggedPointer<T, Tag> &rhs) noexcept
\fn template <typename T, typename Tag> inline bool operator==(std::nullptr_t, QTaggedPointer rhs) noexcept
\relates QTaggedPointer

Returns \c true if \a rhs refers to \c nullptr.
*/

/*!
\fn template <typename T, typename Tag> inline bool operator!=(const QTaggedPointer<T, Tag> &lhs, std::nullptr_t) noexcept
\fn template <typename T, typename Tag> inline bool operator!=(QTaggedPointerlhs, std::nullptr_t) noexcept
\relates QTaggedPointer

Returns \c true if \a lhs refers to a valid (i.e. non-null) pointer.
*/

/*!
\fn template <typename T, typename Tag> inline bool operator!=(std::nullptr_t, const QTaggedPointer<T, Tag> &rhs) noexcept
\fn template <typename T, typename Tag> inline bool operator!=(std::nullptr_t, QTaggedPointer rhs) noexcept
\relates QTaggedPointer

Returns \c true if \a rhs refers to a valid (i.e. non-null) pointer.
*/

/*!
\fn template <typename T, typename Tag> qHash(QTaggedPointer<T, Tag> key, std::size_t seed)
\relates QTaggedPointer

Returns the hash value for the \a key, using \a seed to seed the calculation.
*/

0 comments on commit 5ffa580

Please sign in to comment.