diff options
Diffstat (limited to 'src/corelib/kernel/qpointer.h')
-rw-r--r-- | src/corelib/kernel/qpointer.h | 93 |
1 files changed, 60 insertions, 33 deletions
diff --git a/src/corelib/kernel/qpointer.h b/src/corelib/kernel/qpointer.h index 2c82441164..8875eef5c3 100644 --- a/src/corelib/kernel/qpointer.h +++ b/src/corelib/kernel/qpointer.h @@ -4,6 +4,7 @@ #ifndef QPOINTER_H #define QPOINTER_H +#include <QtCore/qcompare.h> #include <QtCore/qsharedpointer.h> #include <QtCore/qtypeinfo.h> @@ -18,15 +19,48 @@ class QPointer { static_assert(!std::is_pointer<T>::value, "QPointer's template type must not be a pointer type"); + template <typename X> + using if_convertible = std::enable_if_t<std::is_convertible_v<X*, T*>, bool>; + template <typename X> + friend class QPointer; + using QObjectType = typename std::conditional<std::is_const<T>::value, const QObject, QObject>::type; QWeakPointer<QObjectType> wp; public: - QPointer() = default; + Q_NODISCARD_CTOR + QPointer() noexcept = default; + Q_NODISCARD_CTOR + constexpr QPointer(std::nullptr_t) noexcept : QPointer{} {} + Q_WEAK_OVERLOAD + Q_NODISCARD_CTOR inline QPointer(T *p) : wp(p, true) { } // compiler-generated copy/move ctor/assignment operators are fine! // compiler-generated dtor is fine! + template <typename X, if_convertible<X> = true> + Q_NODISCARD_CTOR + QPointer(QPointer<X> &&other) noexcept + : wp(std::exchange(other.wp, nullptr).internalData(), true) {} + template <typename X, if_convertible<X> = true> + Q_NODISCARD_CTOR + QPointer(const QPointer<X> &other) noexcept + : wp(other.wp.internalData(), true) {} + + template <typename X, if_convertible<X> = true> + QPointer &operator=(const QPointer<X> &other) noexcept + { + QPointer(other).swap(*this); + return *this; + } + + template <typename X, if_convertible<X> = true> + QPointer &operator=(QPointer<X> &&other) noexcept + { + QPointer(std::move(other)).swap(*this); + return *this; + } + #ifdef Q_QDOC // Stop qdoc from complaining about missing function ~QPointer(); @@ -37,44 +71,41 @@ public: inline QPointer<T> &operator=(T* p) { wp.assign(static_cast<QObjectType*>(p)); return *this; } - inline T* data() const + T* data() const noexcept { return static_cast<T*>(wp.internalData()); } - inline T* get() const + T* get() const noexcept { return data(); } - inline T* operator->() const + T* operator->() const noexcept { return data(); } - inline T& operator*() const + T& operator*() const noexcept { return *data(); } - inline operator T*() const + operator T*() const noexcept { return data(); } - inline bool isNull() const + bool isNull() const noexcept { return wp.isNull(); } - inline void clear() + void clear() noexcept { wp.clear(); } -#define DECLARE_COMPARE_SET(T1, A1, T2, A2) \ - friend bool operator==(T1, T2) \ - { return A1 == A2; } \ - friend bool operator!=(T1, T2) \ - { return A1 != A2; } - -#define DECLARE_TEMPLATE_COMPARE_SET(T1, A1, T2, A2) \ - template <typename X> \ - friend bool operator==(T1, T2) noexcept \ - { return A1 == A2; } \ - template <typename X> \ - friend bool operator!=(T1, T2) noexcept \ - { return A1 != A2; } - - DECLARE_TEMPLATE_COMPARE_SET(const QPointer &p1, p1.data(), const QPointer<X> &p2, p2.data()) - DECLARE_TEMPLATE_COMPARE_SET(const QPointer &p1, p1.data(), X *ptr, ptr) - DECLARE_TEMPLATE_COMPARE_SET(X *ptr, ptr, const QPointer &p2, p2.data()) - DECLARE_COMPARE_SET(const QPointer &p1, p1.data(), std::nullptr_t, nullptr) - DECLARE_COMPARE_SET(std::nullptr_t, nullptr, const QPointer &p2, p2.data()) -#undef DECLARE_COMPARE_SET -#undef DECLARE_TEMPLATE_COMPARE_SET + friend void swap(QPointer &lhs, QPointer &rhs) noexcept + { lhs.swap(rhs); } + +private: + template <typename X> + friend bool comparesEqual(const QPointer &lhs, const QPointer<X> &rhs) noexcept + { return lhs.data() == rhs.data(); } + QT_DECLARE_EQUALITY_OPERATORS_HELPER(QPointer, QPointer<X>, /* non-constexpr */, + template <typename X>) + + template <typename X> + friend bool comparesEqual(const QPointer &lhs, X *rhs) noexcept + { return lhs.data() == rhs; } + Q_DECLARE_EQUALITY_COMPARABLE(QPointer, X*, template <typename X>) + + friend bool comparesEqual(const QPointer &lhs, std::nullptr_t) noexcept + { return lhs.data() == nullptr; } + Q_DECLARE_EQUALITY_COMPARABLE(QPointer, std::nullptr_t) }; template <class T> Q_DECLARE_TYPEINFO_BODY(QPointer<T>, Q_RELOCATABLE_TYPE); @@ -86,10 +117,6 @@ qPointerFromVariant(const QVariant &variant) return QPointer<T>{qobject_cast<T*>(QtPrivate::EnableInternalData::internalData(wp))}; } -template <class T> -inline void swap(QPointer<T> &p1, QPointer<T> &p2) noexcept -{ p1.swap(p2); } - QT_END_NAMESPACE #endif // QT_NO_QOBJECT |