diff options
Diffstat (limited to 'src/qml/qml/ftw/qqmlrefcount_p.h')
-rw-r--r-- | src/qml/qml/ftw/qqmlrefcount_p.h | 68 |
1 files changed, 51 insertions, 17 deletions
diff --git a/src/qml/qml/ftw/qqmlrefcount_p.h b/src/qml/qml/ftw/qqmlrefcount_p.h index 8b4b5b1535..e7616915eb 100644 --- a/src/qml/qml/ftw/qqmlrefcount_p.h +++ b/src/qml/qml/ftw/qqmlrefcount_p.h @@ -21,23 +21,34 @@ QT_BEGIN_NAMESPACE +template <typename T> +class QQmlRefCounted; -class Q_QML_PRIVATE_EXPORT QQmlRefCount +class QQmlRefCount { Q_DISABLE_COPY_MOVE(QQmlRefCount) public: inline QQmlRefCount(); inline void addref() const; - inline void release() const; inline int count() const; -protected: - inline virtual ~QQmlRefCount(); +private: + inline ~QQmlRefCount(); + template <typename T> friend class QQmlRefCounted; private: mutable QAtomicInt refCount; }; +template <typename T> +class QQmlRefCounted : public QQmlRefCount +{ +public: + inline void release() const; +protected: + inline ~QQmlRefCounted(); +}; + template<class T> class QQmlRefPointer { @@ -46,16 +57,16 @@ public: AddRef, Adopt }; - inline QQmlRefPointer(); - inline QQmlRefPointer(T *, Mode m = AddRef); - inline QQmlRefPointer(const QQmlRefPointer<T> &); - inline QQmlRefPointer(QQmlRefPointer<T> &&); + Q_NODISCARD_CTOR inline QQmlRefPointer() noexcept; + Q_NODISCARD_CTOR inline QQmlRefPointer(T *, Mode m = AddRef); + Q_NODISCARD_CTOR inline QQmlRefPointer(const QQmlRefPointer &); + Q_NODISCARD_CTOR inline QQmlRefPointer(QQmlRefPointer &&) noexcept; inline ~QQmlRefPointer(); void swap(QQmlRefPointer &other) noexcept { qt_ptr_swap(o, other.o); } inline QQmlRefPointer<T> &operator=(const QQmlRefPointer<T> &o); - inline QQmlRefPointer<T> &operator=(QQmlRefPointer<T> &&o); + inline QQmlRefPointer<T> &operator=(QQmlRefPointer<T> &&o) noexcept; inline bool isNull() const { return !o; } @@ -68,8 +79,20 @@ public: inline T* take() { T *res = o; o = nullptr; return res; } - friend bool operator==(const QQmlRefPointer &a, const QQmlRefPointer &b) { return a.o == b.o; } - friend bool operator!=(const QQmlRefPointer &a, const QQmlRefPointer &b) { return !(a == b); } + friend bool operator==(const QQmlRefPointer &a, const QQmlRefPointer &b) noexcept + { + return a.o == b.o; + } + + friend bool operator!=(const QQmlRefPointer &a, const QQmlRefPointer &b) noexcept + { + return !(a == b); + } + + friend size_t qHash(const QQmlRefPointer &v, size_t seed = 0) noexcept + { + return qHash(v.o, seed); + } void reset(T *t = nullptr) { @@ -90,7 +113,7 @@ namespace QQml { /*! \internal Creates a QQmlRefPointer which takes ownership of a newly constructed T. - T must derive from QQmlRefCount (as we rely on an initial refcount of _1_). + T must derive from QQmlRefCounted<T> (as we rely on an initial refcount of _1_). T will be constructed by forwarding \a args to its constructor. */ template <typename T, typename ...Args> @@ -120,11 +143,22 @@ void QQmlRefCount::addref() const refCount.ref(); } -void QQmlRefCount::release() const +template <typename T> +void QQmlRefCounted<T>::release() const { + static_assert(std::is_base_of_v<QQmlRefCounted, T>, + "QQmlRefCounted<T> must be a base of T (CRTP)"); Q_ASSERT(refCount.loadRelaxed() > 0); if (!refCount.deref()) - delete this; + delete static_cast<const T *>(this); +} + +template <typename T> +QQmlRefCounted<T>::~QQmlRefCounted() +{ + static_assert(std::is_final_v<T> || std::has_virtual_destructor_v<T>, + "T must either be marked final or have a virtual dtor, " + "lest release() runs into UB."); } int QQmlRefCount::count() const @@ -133,7 +167,7 @@ int QQmlRefCount::count() const } template<class T> -QQmlRefPointer<T>::QQmlRefPointer() +QQmlRefPointer<T>::QQmlRefPointer() noexcept : o(nullptr) { } @@ -154,7 +188,7 @@ QQmlRefPointer<T>::QQmlRefPointer(const QQmlRefPointer<T> &other) } template <class T> -QQmlRefPointer<T>::QQmlRefPointer(QQmlRefPointer<T> &&other) +QQmlRefPointer<T>::QQmlRefPointer(QQmlRefPointer<T> &&other) noexcept : o(other.take()) { } @@ -179,7 +213,7 @@ QQmlRefPointer<T> &QQmlRefPointer<T>::operator=(const QQmlRefPointer<T> &other) } template <class T> -QQmlRefPointer<T> &QQmlRefPointer<T>::operator=(QQmlRefPointer<T> &&other) +QQmlRefPointer<T> &QQmlRefPointer<T>::operator=(QQmlRefPointer<T> &&other) noexcept { QQmlRefPointer<T> m(std::move(other)); swap(m); |