Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-05 09:27:38

0001 // Copyright (C) 2021 The Qt Company Ltd.
0002 // Copyright (C) 2022 Intel Corporation.
0003 // Copyright (C) 2019 Klarälvdalens Datakonsult AB.
0004 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0005 // Qt-Security score:significant reason:default
0006 
0007 #ifndef Q_QDOC
0008 
0009 #ifndef QSHAREDPOINTER_H
0010 #error Do not include qsharedpointer_impl.h directly
0011 #endif
0012 
0013 #if 0
0014 #pragma qt_sync_skip_header_check
0015 #pragma qt_sync_stop_processing
0016 #endif
0017 
0018 #if 0
0019 // These macros are duplicated here to make syncqt not complain a about
0020 // this header, as we have a "qt_sync_stop_processing" below, which in turn
0021 // is here because this file contains a template mess and duplicates the
0022 // classes found in qsharedpointer.h
0023 QT_BEGIN_NAMESPACE
0024 QT_END_NAMESPACE
0025 #pragma qt_sync_stop_processing
0026 #endif
0027 
0028 #include <new>
0029 #include <QtCore/qatomic.h>
0030 #include <QtCore/qhashfunctions.h>
0031 #include <QtCore/qmetatype.h> // for IsPointerToTypeDerivedFromQObject
0032 #include <QtCore/qxptype_traits.h>
0033 
0034 #include <memory>
0035 
0036 QT_BEGIN_NAMESPACE
0037 
0038 class QObject;
0039 template <class T>
0040 T qobject_cast(const QObject *object);
0041 
0042 //
0043 // forward declarations
0044 //
0045 template <class T> class QWeakPointer;
0046 template <class T> class QSharedPointer;
0047 template <class T> class QEnableSharedFromThis;
0048 
0049 class QVariant;
0050 
0051 template <class X, class T>
0052 QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &ptr);
0053 template <class X, class T>
0054 QSharedPointer<X> qSharedPointerCast(QSharedPointer<T> &&ptr);
0055 template <class X, class T>
0056 QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &ptr);
0057 template <class X, class T>
0058 QSharedPointer<X> qSharedPointerDynamicCast(QSharedPointer<T> &&ptr);
0059 template <class X, class T>
0060 QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &ptr);
0061 template <class X, class T>
0062 QSharedPointer<X> qSharedPointerConstCast(QSharedPointer<T> &&ptr);
0063 
0064 #ifndef QT_NO_QOBJECT
0065 template <class X, class T>
0066 QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &ptr);
0067 template <class X, class T>
0068 QSharedPointer<X> qSharedPointerObjectCast(QSharedPointer<T> &&ptr);
0069 #endif
0070 
0071 namespace QtPrivate {
0072 struct EnableInternalData;
0073 }
0074 
0075 namespace QtSharedPointer {
0076     template <class T> class ExternalRefCount;
0077 
0078     template <class X, class Y> QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
0079     template <class X, class Y> QSharedPointer<X> movePointer(X * ptr, QSharedPointer<Y> &&src);
0080 
0081     // used in debug mode to verify the reuse of pointers
0082     Q_CORE_EXPORT void internalSafetyCheckAdd(const void *, const volatile void *);
0083     Q_CORE_EXPORT void internalSafetyCheckRemove(const void *);
0084 
0085     template <class T, typename Klass, typename RetVal>
0086     inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)())
0087     { if (t) (t->*memberDeleter)(); }
0088     template <class T, typename Deleter>
0089     inline void executeDeleter(T *t, Deleter d)
0090     { d(t); }
0091     struct NormalDeleter {};
0092 
0093     // this uses partial template specialization
0094     template <class T> struct RemovePointer;
0095     template <class T> struct RemovePointer<T *> { typedef T Type; };
0096     template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; };
0097     template <class T> struct RemovePointer<QWeakPointer<T> > { typedef T Type; };
0098 
0099     // This class is the d-pointer of QSharedPointer and QWeakPointer.
0100     //
0101     // It is a reference-counted reference counter. "strongref" is the inner
0102     // reference counter, and it tracks the lifetime of the pointer itself.
0103     // "weakref" is the outer reference counter and it tracks the lifetime of
0104     // the ExternalRefCountData object.
0105     //
0106     // The deleter is stored in the destroyer member and is always a pointer to
0107     // a static function in ExternalRefCountWithCustomDeleter or in
0108     // ExternalRefCountWithContiguousData
0109     struct ExternalRefCountData
0110     {
0111         typedef void (*DestroyerFn)(ExternalRefCountData *);
0112         QBasicAtomicInt weakref;
0113         QBasicAtomicInt strongref;
0114         DestroyerFn destroyer;
0115 
0116         inline ExternalRefCountData(DestroyerFn d)
0117             : destroyer(d)
0118         {
0119             strongref.storeRelaxed(1);
0120             weakref.storeRelaxed(1);
0121         }
0122         inline ExternalRefCountData(Qt::Initialization) { }
0123         ~ExternalRefCountData() { Q_ASSERT(!weakref.loadRelaxed()); Q_ASSERT(strongref.loadRelaxed() <= 0); }
0124 
0125         void destroy() { destroyer(this); }
0126 
0127 #ifndef QT_NO_QOBJECT
0128         Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *);
0129         QT6_ONLY(
0130         Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable);
0131         )
0132         QT6_ONLY(Q_CORE_EXPORT void checkQObjectShared(const QObject *);)
0133 #endif
0134         inline void checkQObjectShared(...) { }
0135         inline void setQObjectShared(...) { }
0136 
0137         // Normally, only subclasses of ExternalRefCountData are allocated
0138         // One exception exists in getAndRef; that uses the global operator new
0139         // to prevent a mismatch with the custom operator delete
0140         inline void *operator new(std::size_t) = delete;
0141         // placement new
0142         inline void *operator new(std::size_t, void *ptr) noexcept { return ptr; }
0143         inline void operator delete(void *ptr) { ::operator delete(ptr); }
0144         inline void operator delete(void *, void *) { }
0145     };
0146     // sizeof(ExternalRefCountData) = 12 (32-bit) / 16 (64-bit)
0147 
0148     template <class T, typename Deleter>
0149     struct CustomDeleter
0150     {
0151         Deleter deleter;
0152         T *ptr;
0153 
0154         CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {}
0155         void execute() { executeDeleter(ptr, deleter); }
0156     };
0157     // sizeof(CustomDeleter) = sizeof(Deleter) + sizeof(void*) + padding
0158     // for Deleter = stateless functor: 8 (32-bit) / 16 (64-bit) due to padding
0159     // for Deleter = function pointer:  8 (32-bit) / 16 (64-bit)
0160     // for Deleter = PMF: 12 (32-bit) / 24 (64-bit)  (GCC)
0161 
0162     // This specialization of CustomDeleter for a deleter of type NormalDeleter
0163     // is an optimization: instead of storing a pointer to a function that does
0164     // the deleting, we simply delete the pointer ourselves.
0165     template <class T>
0166     struct CustomDeleter<T, NormalDeleter>
0167     {
0168         T *ptr;
0169 
0170         CustomDeleter(T *p, NormalDeleter) : ptr(p) {}
0171         void execute() { delete ptr; }
0172     };
0173     // sizeof(CustomDeleter specialization) = sizeof(void*)
0174 
0175     // This class extends ExternalRefCountData and implements
0176     // the static function that deletes the object. The pointer and the
0177     // custom deleter are kept in the "extra" member so we can construct
0178     // and destruct it independently of the full structure.
0179     template <class T, typename Deleter>
0180     struct ExternalRefCountWithCustomDeleter: public ExternalRefCountData
0181     {
0182         typedef ExternalRefCountWithCustomDeleter Self;
0183         typedef ExternalRefCountData BaseClass;
0184         CustomDeleter<T, Deleter> extra;
0185 
0186         static inline void deleter(ExternalRefCountData *self)
0187         {
0188             Self *realself = static_cast<Self *>(self);
0189             realself->extra.execute();
0190 
0191             // delete the deleter too
0192             realself->extra.~CustomDeleter<T, Deleter>();
0193         }
0194         static void safetyCheckDeleter(ExternalRefCountData *self)
0195         {
0196             internalSafetyCheckRemove(self);
0197             deleter(self);
0198         }
0199 
0200         static inline Self *create(T *ptr, Deleter userDeleter, DestroyerFn actualDeleter)
0201         {
0202             Self *d = static_cast<Self *>(::operator new(sizeof(Self)));
0203 
0204             // initialize the two sub-objects
0205             new (&d->extra) CustomDeleter<T, Deleter>(ptr, userDeleter);
0206             new (d) BaseClass(actualDeleter); // can't throw
0207 
0208             return d;
0209         }
0210     private:
0211         // prevent construction
0212         ExternalRefCountWithCustomDeleter() = delete;
0213         ~ExternalRefCountWithCustomDeleter() = delete;
0214         Q_DISABLE_COPY(ExternalRefCountWithCustomDeleter)
0215     };
0216 
0217     // This class extends ExternalRefCountData and adds a "T"
0218     // member. That way, when the create() function is called, we allocate
0219     // memory for both QSharedPointer's d-pointer and the actual object being
0220     // tracked.
0221     template <class T>
0222     struct ExternalRefCountWithContiguousData: public ExternalRefCountData
0223     {
0224         typedef ExternalRefCountData Parent;
0225         typedef typename std::remove_cv<T>::type NoCVType;
0226         NoCVType data;
0227 
0228         static void deleter(ExternalRefCountData *self)
0229         {
0230             ExternalRefCountWithContiguousData *that =
0231                     static_cast<ExternalRefCountWithContiguousData *>(self);
0232             that->data.~T();
0233             Q_UNUSED(that); // MSVC warns if T has a trivial destructor
0234         }
0235         static void safetyCheckDeleter(ExternalRefCountData *self)
0236         {
0237             internalSafetyCheckRemove(self);
0238             deleter(self);
0239         }
0240         static void noDeleter(ExternalRefCountData *) { }
0241 
0242         static inline ExternalRefCountData *create(NoCVType **ptr, DestroyerFn destroy)
0243         {
0244             ExternalRefCountWithContiguousData *d =
0245                 static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData)));
0246 
0247             // initialize the d-pointer sub-object
0248             // leave d->data uninitialized
0249             new (d) Parent(destroy); // can't throw
0250 
0251             *ptr = &d->data;
0252             return d;
0253         }
0254 
0255     private:
0256         // prevent construction
0257         ExternalRefCountWithContiguousData() = delete;
0258         ~ExternalRefCountWithContiguousData() = delete;
0259         Q_DISABLE_COPY(ExternalRefCountWithContiguousData)
0260     };
0261 
0262 #ifndef QT_NO_QOBJECT
0263     Q_CORE_EXPORT QWeakPointer<QObject> weakPointerFromVariant_internal(const QVariant &variant);
0264     Q_CORE_EXPORT QSharedPointer<QObject> sharedPointerFromVariant_internal(const QVariant &variant);
0265 #endif
0266 } // namespace QtSharedPointer
0267 
0268 template <class T> class QSharedPointer
0269 {
0270     typedef QtSharedPointer::ExternalRefCountData Data;
0271     template <typename X>
0272     using IfCompatible = typename std::enable_if<std::is_convertible<X*, T*>::value, bool>::type;
0273 
0274 public:
0275     typedef T Type;
0276     typedef T element_type;
0277     typedef T value_type;
0278     typedef value_type *pointer;
0279     typedef const value_type *const_pointer;
0280     typedef value_type &reference;
0281     typedef const value_type &const_reference;
0282     typedef qptrdiff difference_type;
0283 
0284     T *data() const noexcept { return value.get(); }
0285     T *get() const noexcept { return value.get(); }
0286     bool isNull() const noexcept { return !data(); }
0287     explicit operator bool() const noexcept { return !isNull(); }
0288     bool operator !() const noexcept { return isNull(); }
0289     T &operator*() const { return *data(); }
0290     T *operator->() const noexcept { return data(); }
0291 
0292     Q_NODISCARD_CTOR
0293     constexpr QSharedPointer() noexcept : value(nullptr), d(nullptr) { }
0294     ~QSharedPointer() { deref(); }
0295 
0296     Q_NODISCARD_CTOR
0297     constexpr QSharedPointer(std::nullptr_t) noexcept : value(nullptr), d(nullptr) { }
0298 
0299     template <class X, IfCompatible<X> = true>
0300     Q_NODISCARD_CTOR
0301     inline explicit QSharedPointer(X *ptr) : value(ptr) // noexcept
0302     { internalConstruct(ptr, QtSharedPointer::NormalDeleter()); }
0303 
0304     template <class X, typename Deleter, IfCompatible<X> = true>
0305     Q_NODISCARD_CTOR
0306     inline QSharedPointer(X *ptr, Deleter deleter) : value(ptr) // throws
0307     { internalConstruct(ptr, deleter); }
0308 
0309     template <typename Deleter>
0310     Q_NODISCARD_CTOR
0311     QSharedPointer(std::nullptr_t, Deleter deleter) : value(nullptr)
0312     { internalConstruct(static_cast<T *>(nullptr), deleter); }
0313 
0314     Q_NODISCARD_CTOR
0315     QSharedPointer(const QSharedPointer &other) noexcept : value(other.value.get()), d(other.d)
0316     { if (d) ref(); }
0317     QSharedPointer &operator=(const QSharedPointer &other) noexcept
0318     {
0319         QSharedPointer copy(other);
0320         swap(copy);
0321         return *this;
0322     }
0323     Q_NODISCARD_CTOR
0324     QSharedPointer(QSharedPointer &&other) noexcept
0325         : value(other.value.get()), d(other.d)
0326     {
0327         other.d = nullptr;
0328         other.value = nullptr;
0329     }
0330     QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSharedPointer)
0331 
0332     template <class X, IfCompatible<X> = true>
0333     Q_NODISCARD_CTOR
0334     QSharedPointer(QSharedPointer<X> &&other) noexcept
0335         : value(other.value.get()), d(other.d)
0336     {
0337         other.d = nullptr;
0338         other.value = nullptr;
0339     }
0340 
0341     template <class X, IfCompatible<X> = true>
0342     QSharedPointer &operator=(QSharedPointer<X> &&other) noexcept
0343     {
0344         QSharedPointer moved(std::move(other));
0345         swap(moved);
0346         return *this;
0347     }
0348 
0349     template <class X, IfCompatible<X> = true>
0350     Q_NODISCARD_CTOR
0351     QSharedPointer(const QSharedPointer<X> &other) noexcept : value(other.value.get()), d(other.d)
0352     { if (d) ref(); }
0353 
0354     template <class X, IfCompatible<X> = true>
0355     inline QSharedPointer &operator=(const QSharedPointer<X> &other)
0356     {
0357         QSharedPointer copy(other);
0358         swap(copy);
0359         return *this;
0360     }
0361 
0362     template <class X, IfCompatible<X> = true>
0363     Q_NODISCARD_CTOR
0364     inline QSharedPointer(const QWeakPointer<X> &other) : value(nullptr), d(nullptr)
0365     { *this = other; }
0366 
0367     template <class X, IfCompatible<X> = true>
0368     inline QSharedPointer<T> &operator=(const QWeakPointer<X> &other)
0369     { internalSet(other.d, other.value); return *this; }
0370 
0371     inline void swap(QSharedPointer &other) noexcept
0372     { this->internalSwap(other); }
0373 
0374     inline void reset() { clear(); }
0375     inline void reset(T *t)
0376     { QSharedPointer copy(t); swap(copy); }
0377     template <typename Deleter>
0378     inline void reset(T *t, Deleter deleter)
0379     { QSharedPointer copy(t, deleter); swap(copy); }
0380 
0381     template <class X>
0382     QSharedPointer<X> staticCast() const &
0383     {
0384         return qSharedPointerCast<X>(*this);
0385     }
0386 
0387     template <class X>
0388     QSharedPointer<X> staticCast() &&
0389     {
0390         return qSharedPointerCast<X>(std::move(*this));
0391     }
0392 
0393     template <class X>
0394     QSharedPointer<X> dynamicCast() const &
0395     {
0396         return qSharedPointerDynamicCast<X>(*this);
0397     }
0398 
0399     template <class X>
0400     QSharedPointer<X> dynamicCast() &&
0401     {
0402         return qSharedPointerDynamicCast<X>(std::move(*this));
0403     }
0404 
0405     template <class X>
0406     QSharedPointer<X> constCast() const &
0407     {
0408         return qSharedPointerConstCast<X>(*this);
0409     }
0410 
0411     template <class X>
0412     QSharedPointer<X> constCast() &&
0413     {
0414         return qSharedPointerConstCast<X>(std::move(*this));
0415     }
0416 
0417 #ifndef QT_NO_QOBJECT
0418     template <class X>
0419     QSharedPointer<X> objectCast() const &
0420     {
0421         return qSharedPointerObjectCast<X>(*this);
0422     }
0423 
0424     template <class X>
0425     QSharedPointer<X> objectCast() &&
0426     {
0427         return qSharedPointerObjectCast<X>(std::move(*this));
0428     }
0429 #endif
0430 
0431     inline void clear() { QSharedPointer copy; swap(copy); }
0432 
0433     [[nodiscard]] QWeakPointer<T> toWeakRef() const;
0434 
0435     template <typename... Args>
0436     [[nodiscard]] static QSharedPointer create(Args && ...arguments)
0437     {
0438         typedef QtSharedPointer::ExternalRefCountWithContiguousData<T> Private;
0439 # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
0440         typename Private::DestroyerFn destroy = &Private::safetyCheckDeleter;
0441 # else
0442         typename Private::DestroyerFn destroy = &Private::deleter;
0443 # endif
0444         typename Private::DestroyerFn noDestroy = &Private::noDeleter;
0445         QSharedPointer result(Qt::Uninitialized);
0446         typename std::remove_cv<T>::type *ptr;
0447         result.d = Private::create(&ptr, noDestroy);
0448 
0449         // now initialize the data
0450         new (ptr) T(std::forward<Args>(arguments)...);
0451         result.value.reset(ptr);
0452         result.d->destroyer = destroy;
0453         result.d->setQObjectShared(result.value.get(), true);
0454 # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
0455         internalSafetyCheckAdd(result.d, result.value.get());
0456 # endif
0457         result.enableSharedFromThis(result.data());
0458         return result;
0459     }
0460 
0461     template <typename X>
0462     bool owner_before(const QSharedPointer<X> &other) const noexcept
0463     { return std::less<>()(d, other.d); }
0464     template <typename X>
0465     bool owner_before(const QWeakPointer<X> &other) const noexcept
0466     { return std::less<>()(d, other.d); }
0467 
0468     template <typename X>
0469     bool owner_equal(const QSharedPointer<X> &other) const noexcept
0470     { return d == other.d; }
0471     template <typename X>
0472     bool owner_equal(const QWeakPointer<X> &other) const noexcept
0473     { return d == other.d; }
0474 
0475     size_t owner_hash() const noexcept
0476     { return std::hash<Data *>()(d); }
0477 
0478 private:
0479     template <typename X>
0480     friend bool comparesEqual(const QSharedPointer &lhs, const QSharedPointer<X> &rhs) noexcept
0481     { return lhs.data() == rhs.data(); }
0482     template <typename X>
0483     friend Qt::strong_ordering
0484     compareThreeWay(const QSharedPointer &lhs, const QSharedPointer<X> &rhs) noexcept
0485     {
0486         return Qt::compareThreeWay(lhs.value, rhs.data());
0487     }
0488     QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, QSharedPointer<T>, QSharedPointer<X>,
0489                                          /* non-constexpr */, noexcept(true),
0490                                          template <typename X>)
0491 
0492     template <typename X>
0493     friend bool comparesEqual(const QSharedPointer &lhs, X *rhs) noexcept
0494     { return lhs.data() == rhs; }
0495     template <typename X>
0496     friend Qt::strong_ordering compareThreeWay(const QSharedPointer &lhs, X *rhs) noexcept
0497     { return Qt::compareThreeWay(lhs.value, rhs); }
0498     Q_DECLARE_STRONGLY_ORDERED(QSharedPointer, X*, template <typename X>)
0499 
0500     friend bool comparesEqual(const QSharedPointer &lhs, std::nullptr_t) noexcept
0501     { return lhs.data() == nullptr; }
0502     friend Qt::strong_ordering
0503     compareThreeWay(const QSharedPointer &lhs, std::nullptr_t) noexcept
0504     { return Qt::compareThreeWay(lhs.value, nullptr); }
0505     Q_DECLARE_STRONGLY_ORDERED(QSharedPointer, std::nullptr_t)
0506 
0507     Q_NODISCARD_CTOR
0508     explicit QSharedPointer(Qt::Initialization) {}
0509 
0510     void deref() noexcept
0511     { deref(d); }
0512     static void deref(Data *dd) noexcept
0513     {
0514         if (!dd) return;
0515         if (!dd->strongref.deref()) {
0516             dd->destroy();
0517         }
0518         if (!dd->weakref.deref())
0519             delete dd;
0520     }
0521 
0522     template <class X>
0523     inline void enableSharedFromThis(const QEnableSharedFromThis<X> *ptr)
0524     {
0525         ptr->initializeFromSharedPointer(constCast<typename std::remove_cv<T>::type>());
0526     }
0527 
0528     inline void enableSharedFromThis(...) {}
0529 
0530     template <typename X, typename Deleter>
0531     inline void internalConstruct(X *ptr, Deleter deleter)
0532     {
0533         typedef QtSharedPointer::ExternalRefCountWithCustomDeleter<X, Deleter> Private;
0534 # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
0535         typename Private::DestroyerFn actualDeleter = &Private::safetyCheckDeleter;
0536 # else
0537         typename Private::DestroyerFn actualDeleter = &Private::deleter;
0538 # endif
0539         d = Private::create(ptr, deleter, actualDeleter);
0540 
0541 #ifdef QT_SHAREDPOINTER_TRACK_POINTERS
0542         internalSafetyCheckAdd(d, ptr);
0543 #endif
0544         enableSharedFromThis(ptr);
0545     }
0546 
0547     void internalSwap(QSharedPointer &other) noexcept
0548     {
0549         qt_ptr_swap(d, other.d);
0550         qt_ptr_swap(this->value, other.value);
0551     }
0552 
0553     template <class X> friend class QSharedPointer;
0554     template <class X> friend class QWeakPointer;
0555     template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
0556     template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::movePointer(X * ptr, QSharedPointer<Y> &&src);
0557     void ref() const noexcept { d->weakref.ref(); d->strongref.ref(); }
0558 
0559     inline void internalSet(Data *o, T *actual)
0560     {
0561         if (o) {
0562             // increase the strongref, but never up from zero
0563             // or less (-1 is used by QWeakPointer on untracked QObject)
0564             int tmp = o->strongref.loadRelaxed();
0565             while (tmp > 0) {
0566                 // try to increment from "tmp" to "tmp + 1"
0567                 if (o->strongref.testAndSetRelaxed(tmp, tmp + 1))
0568                     break;   // succeeded
0569                 tmp = o->strongref.loadRelaxed();  // failed, try again
0570             }
0571 
0572             if (tmp > 0)
0573                 o->weakref.ref();
0574             else
0575                 o = nullptr;
0576         }
0577 
0578         qt_ptr_swap(d, o);
0579         this->value.reset(actual);
0580         if (!d || d->strongref.loadRelaxed() == 0)
0581             this->value = nullptr;
0582 
0583         // dereference saved data
0584         deref(o);
0585     }
0586 
0587     Qt::totally_ordered_wrapper<Type *> value;
0588     Data *d;
0589 };
0590 
0591 template <class T>
0592 class QWeakPointer
0593 {
0594     typedef QtSharedPointer::ExternalRefCountData Data;
0595     template <typename X>
0596     using IfCompatible = std::enable_if_t<std::conjunction_v<
0597             std::negation<std::is_same<T, X>>, // don't make accidental copy/move SMFs
0598             std::is_convertible<X*, T*>
0599         >, bool>;
0600 
0601     template <typename X>
0602     using IfVirtualBase = typename std::enable_if<qxp::is_virtual_base_of_v<T, X>, bool>::type;
0603 
0604     template <typename X>
0605     using IfNotVirtualBase = typename std::enable_if<!qxp::is_virtual_base_of_v<T, X>, bool>::type;
0606 
0607 public:
0608     typedef T element_type;
0609     typedef T value_type;
0610     typedef value_type *pointer;
0611     typedef const value_type *const_pointer;
0612     typedef value_type &reference;
0613     typedef const value_type &const_reference;
0614     typedef qptrdiff difference_type;
0615 
0616     bool isNull() const noexcept { return d == nullptr || d->strongref.loadRelaxed() == 0 || value == nullptr; }
0617     explicit operator bool() const noexcept { return !isNull(); }
0618     bool operator !() const noexcept { return isNull(); }
0619 
0620     Q_NODISCARD_CTOR
0621     constexpr QWeakPointer() noexcept : d(nullptr), value(nullptr) { }
0622     inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
0623 
0624     Q_NODISCARD_CTOR
0625     QWeakPointer(const QWeakPointer &other) noexcept : d(other.d), value(other.value)
0626     { if (d) d->weakref.ref(); }
0627     Q_NODISCARD_CTOR
0628     QWeakPointer(QWeakPointer &&other) noexcept
0629         : d(other.d), value(other.value)
0630     {
0631         other.d = nullptr;
0632         other.value = nullptr;
0633     }
0634     QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QWeakPointer)
0635 
0636     template <class X, IfCompatible<X> = true, IfNotVirtualBase<X> = true>
0637     Q_NODISCARD_CTOR
0638     QWeakPointer(QWeakPointer<X> &&other) noexcept
0639         : d(std::exchange(other.d, nullptr)),
0640           value(std::exchange(other.value, nullptr))
0641     {
0642     }
0643 
0644     template <class X, IfCompatible<X> = true, IfVirtualBase<X> = true>
0645     Q_NODISCARD_CTOR
0646     QWeakPointer(QWeakPointer<X> &&other) noexcept
0647         : d(other.d), value(other.toStrongRef().get()) // must go through QSharedPointer, see below
0648     {
0649         other.d = nullptr;
0650         other.value = nullptr;
0651     }
0652 
0653     template <class X, IfCompatible<X> = true>
0654     QWeakPointer &operator=(QWeakPointer<X> &&other) noexcept
0655     {
0656         QWeakPointer moved(std::move(other));
0657         swap(moved);
0658         return *this;
0659     }
0660 
0661     QWeakPointer &operator=(const QWeakPointer &other) noexcept
0662     {
0663         QWeakPointer copy(other);
0664         swap(copy);
0665         return *this;
0666     }
0667 
0668     void swap(QWeakPointer &other) noexcept
0669     {
0670         qt_ptr_swap(this->d, other.d);
0671         qt_ptr_swap(this->value, other.value);
0672     }
0673 
0674     Q_NODISCARD_CTOR
0675     inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data())
0676     { if (d) d->weakref.ref();}
0677     inline QWeakPointer &operator=(const QSharedPointer<T> &o)
0678     {
0679         internalSet(o.d, o.value.get());
0680         return *this;
0681     }
0682 
0683     template <class X, IfCompatible<X> = true>
0684     Q_NODISCARD_CTOR
0685     inline QWeakPointer(const QWeakPointer<X> &o) : d(nullptr), value(nullptr)
0686     { *this = o; }
0687 
0688     template <class X, IfCompatible<X> = true>
0689     inline QWeakPointer &operator=(const QWeakPointer<X> &o)
0690     {
0691         // conversion between X and T could require access to the virtual table
0692         // so force the operation to go through QSharedPointer
0693         *this = o.toStrongRef();
0694         return *this;
0695     }
0696 
0697     template <class X, IfCompatible<X> = true>
0698     Q_NODISCARD_CTOR
0699     inline QWeakPointer(const QSharedPointer<X> &o) : d(nullptr), value(nullptr)
0700     { *this = o; }
0701 
0702     template <class X, IfCompatible<X> = true>
0703     inline QWeakPointer &operator=(const QSharedPointer<X> &o)
0704     {
0705         internalSet(o.d, o.data());
0706         return *this;
0707     }
0708 
0709     inline void clear() { *this = QWeakPointer(); }
0710 
0711     [[nodiscard]] QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
0712     // std::weak_ptr compatibility:
0713     [[nodiscard]] QSharedPointer<T> lock() const { return toStrongRef(); }
0714 
0715     template <class X>
0716     bool operator==(const QWeakPointer<X> &o) const noexcept
0717     { return d == o.d && value == static_cast<const T *>(o.value); }
0718 
0719     template <class X>
0720     bool operator!=(const QWeakPointer<X> &o) const noexcept
0721     { return !(*this == o); }
0722 
0723     template <class X>
0724     bool operator==(const QSharedPointer<X> &o) const noexcept
0725     { return d == o.d; }
0726 
0727     template <class X>
0728     bool operator!=(const QSharedPointer<X> &o) const noexcept
0729     { return !(*this == o); }
0730 
0731     template <typename X>
0732     friend bool operator==(const QSharedPointer<X> &p1, const QWeakPointer &p2) noexcept
0733     { return p2 == p1; }
0734     template <typename X>
0735     friend bool operator!=(const QSharedPointer<X> &p1, const QWeakPointer &p2) noexcept
0736     { return p2 != p1; }
0737 
0738     friend bool operator==(const QWeakPointer &p, std::nullptr_t)
0739     { return p.isNull(); }
0740     friend bool operator==(std::nullptr_t, const QWeakPointer &p)
0741     { return p.isNull(); }
0742     friend bool operator!=(const QWeakPointer &p, std::nullptr_t)
0743     { return !p.isNull(); }
0744     friend bool operator!=(std::nullptr_t, const QWeakPointer &p)
0745     { return !p.isNull(); }
0746 
0747     template <typename X>
0748     bool owner_before(const QWeakPointer<X> &other) const noexcept
0749     { return std::less<>()(d, other.d); }
0750     template <typename X>
0751     bool owner_before(const QSharedPointer<X> &other) const noexcept
0752     { return std::less<>()(d, other.d); }
0753 
0754     template <typename X>
0755     bool owner_equal(const QWeakPointer<X> &other) const noexcept
0756     { return d == other.d; }
0757     template <typename X>
0758     bool owner_equal(const QSharedPointer<X> &other) const noexcept
0759     { return d == other.d; }
0760 
0761     size_t owner_hash() const noexcept
0762     { return std::hash<Data *>()(d); }
0763 
0764 private:
0765     friend struct QtPrivate::EnableInternalData;
0766     template <class X> friend class QSharedPointer;
0767     template <class X> friend class QWeakPointer;
0768     template <class X> friend class QPointer;
0769 
0770     template <class X>
0771     inline QWeakPointer &assign(X *ptr)
0772     { return *this = QWeakPointer<T>(ptr, true); }
0773 
0774 #ifndef QT_NO_QOBJECT
0775     Q_NODISCARD_CTOR
0776     QWeakPointer(T *ptr, bool)
0777         : d{ptr ? Data::getAndRef(ptr) : nullptr}, value{ptr}
0778     { }
0779 
0780     template <class X, IfCompatible<X> = true>
0781     Q_NODISCARD_CTOR
0782     inline QWeakPointer(X *ptr, bool) : d(ptr ? Data::getAndRef(ptr) : nullptr), value(ptr)
0783     { }
0784 #endif
0785 
0786     inline void internalSet(Data *o, T *actual)
0787     {
0788         if (d == o) return;
0789         if (o)
0790             o->weakref.ref();
0791         if (d && !d->weakref.deref())
0792             delete d;
0793         d = o;
0794         value = actual;
0795     }
0796 
0797     // ### TODO - QTBUG-88102: remove all users of this API; no one should ever
0798     // access a weak pointer's data but the weak pointer itself
0799     inline T *internalData() const noexcept
0800     {
0801         return d == nullptr || d->strongref.loadRelaxed() == 0 ? nullptr : value;
0802     }
0803 
0804     Data *d;
0805     T *value;
0806 };
0807 
0808 namespace QtPrivate {
0809 struct EnableInternalData {
0810     template <typename T>
0811     static T *internalData(const QWeakPointer<T> &p) noexcept { return p.internalData(); }
0812 };
0813 // hack to delay name lookup to instantiation time by making
0814 // EnableInternalData a dependent name:
0815 template <typename T>
0816 struct EnableInternalDataWrap : EnableInternalData {};
0817 }
0818 
0819 template <class T>
0820 class QEnableSharedFromThis
0821 {
0822 protected:
0823     QEnableSharedFromThis() = default;
0824     QEnableSharedFromThis(const QEnableSharedFromThis &) {}
0825     QEnableSharedFromThis &operator=(const QEnableSharedFromThis &) { return *this; }
0826 
0827 public:
0828     inline QSharedPointer<T> sharedFromThis() { return QSharedPointer<T>(weakPointer); }
0829     inline QSharedPointer<const T> sharedFromThis() const { return QSharedPointer<const T>(weakPointer); }
0830 
0831 private:
0832     template <class X> friend class QSharedPointer;
0833     template <class X>
0834     inline void initializeFromSharedPointer(const QSharedPointer<X> &ptr) const
0835     {
0836         weakPointer = ptr;
0837     }
0838 
0839     mutable QWeakPointer<T> weakPointer;
0840 };
0841 
0842 //
0843 // operator-
0844 //
0845 template <class T, class X>
0846 Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
0847 {
0848     return ptr1.data() - ptr2.data();
0849 }
0850 template <class T, class X>
0851 Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, X *ptr2)
0852 {
0853     return ptr1.data() - ptr2;
0854 }
0855 template <class T, class X>
0856 Q_INLINE_TEMPLATE typename QSharedPointer<X>::difference_type operator-(T *ptr1, const QSharedPointer<X> &ptr2)
0857 {
0858     return ptr1 - ptr2.data();
0859 }
0860 
0861 //
0862 // qHash
0863 //
0864 template <class T>
0865 Q_INLINE_TEMPLATE size_t qHash(const QSharedPointer<T> &ptr, size_t seed = 0)
0866 {
0867     return qHash(ptr.data(), seed);
0868 }
0869 
0870 
0871 template <class T>
0872 Q_INLINE_TEMPLATE QWeakPointer<T> QSharedPointer<T>::toWeakRef() const
0873 {
0874     return QWeakPointer<T>(*this);
0875 }
0876 
0877 template <class T>
0878 inline void swap(QSharedPointer<T> &p1, QSharedPointer<T> &p2) noexcept
0879 { p1.swap(p2); }
0880 
0881 template <class T>
0882 inline void swap(QWeakPointer<T> &p1, QWeakPointer<T> &p2) noexcept
0883 { p1.swap(p2); }
0884 
0885 namespace QtSharedPointer {
0886 // helper functions:
0887     template <class X, class T>
0888     Q_INLINE_TEMPLATE QSharedPointer<X> copyAndSetPointer(X *ptr, const QSharedPointer<T> &src)
0889     {
0890         QSharedPointer<X> result;
0891         result.internalSet(src.d, ptr);
0892         return result;
0893     }
0894 
0895     template <class X, class T>
0896     Q_INLINE_TEMPLATE QSharedPointer<X> movePointer(X *ptr, QSharedPointer<T> &&src)
0897     {
0898         QSharedPointer<X> result;
0899         result.d = std::exchange(src.d, nullptr);
0900         result.value.reset(ptr);
0901         src.value.reset(nullptr);
0902         return result;
0903     }
0904 }
0905 
0906 // cast operators
0907 template <class X, class T>
0908 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &src)
0909 {
0910     X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
0911     return QtSharedPointer::copyAndSetPointer(ptr, src);
0912 }
0913 template <class X, class T>
0914 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(QSharedPointer<T> &&src)
0915 {
0916     X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
0917     return QtSharedPointer::movePointer(ptr, std::move(src));
0918 }
0919 template <class X, class T>
0920 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &src)
0921 {
0922     return qSharedPointerCast<X>(src.toStrongRef());
0923 }
0924 
0925 template <class X, class T>
0926 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src)
0927 {
0928     X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
0929     if (!ptr)
0930         return QSharedPointer<X>();
0931     return QtSharedPointer::copyAndSetPointer(ptr, src);
0932 }
0933 template <class X, class T>
0934 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(QSharedPointer<T> &&src)
0935 {
0936     X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
0937     if (!ptr)
0938         return QSharedPointer<X>();
0939     return QtSharedPointer::movePointer(ptr, std::move(src));
0940 }
0941 template <class X, class T>
0942 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src)
0943 {
0944     return qSharedPointerDynamicCast<X>(src.toStrongRef());
0945 }
0946 
0947 template <class X, class T>
0948 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src)
0949 {
0950     X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
0951     return QtSharedPointer::copyAndSetPointer(ptr, src);
0952 }
0953 template <class X, class T>
0954 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(QSharedPointer<T> &&src)
0955 {
0956     X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
0957     return QtSharedPointer::movePointer(ptr, std::move(src));
0958 }
0959 template <class X, class T>
0960 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src)
0961 {
0962     return qSharedPointerConstCast<X>(src.toStrongRef());
0963 }
0964 
0965 template <class X, class T>
0966 Q_INLINE_TEMPLATE
0967 QWeakPointer<X> qWeakPointerCast(const QSharedPointer<T> &src)
0968 {
0969     return qSharedPointerCast<X>(src).toWeakRef();
0970 }
0971 
0972 #ifndef QT_NO_QOBJECT
0973 template <class X, class T>
0974 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src)
0975 {
0976     X *ptr = qobject_cast<X *>(src.data());
0977     if (!ptr)
0978         return QSharedPointer<X>();
0979     return QtSharedPointer::copyAndSetPointer(ptr, src);
0980 }
0981 template <class X, class T>
0982 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(QSharedPointer<T> &&src)
0983 {
0984     X *ptr = qobject_cast<X *>(src.data());
0985     if (!ptr)
0986         return QSharedPointer<X>();
0987     return QtSharedPointer::movePointer(ptr, std::move(src));
0988 }
0989 template <class X, class T>
0990 Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src)
0991 {
0992     return qSharedPointerObjectCast<X>(src.toStrongRef());
0993 }
0994 
0995 template <class X, class T>
0996 inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
0997 qobject_cast(const QSharedPointer<T> &src)
0998 {
0999     return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type>(src);
1000 }
1001 template <class X, class T>
1002 inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
1003 qobject_cast(QSharedPointer<T> &&src)
1004 {
1005     return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type>(std::move(src));
1006 }
1007 template <class X, class T>
1008 inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
1009 qobject_cast(const QWeakPointer<T> &src)
1010 {
1011     return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type>(src);
1012 }
1013 
1014 /// ### TODO - QTBUG-88102: make this use toStrongRef() (once support for
1015 /// storing non-managed QObjects in QWeakPointer is removed)
1016 template<typename T>
1017 QWeakPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
1018 qWeakPointerFromVariant(const QVariant &variant)
1019 {
1020     return QWeakPointer<T>(qobject_cast<T*>(QtPrivate::EnableInternalData::internalData(QtSharedPointer::weakPointerFromVariant_internal(variant))));
1021 }
1022 template<typename T>
1023 QSharedPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
1024 qSharedPointerFromVariant(const QVariant &variant)
1025 {
1026     return qSharedPointerObjectCast<T>(QtSharedPointer::sharedPointerFromVariant_internal(variant));
1027 }
1028 
1029 // std::shared_ptr helpers
1030 
1031 template <typename X, class T>
1032 std::shared_ptr<X> qobject_pointer_cast(const std::shared_ptr<T> &src)
1033 {
1034     using element_type = typename std::shared_ptr<X>::element_type;
1035     if (auto ptr = qobject_cast<element_type *>(src.get()))
1036         return std::shared_ptr<X>(src, ptr);
1037     return std::shared_ptr<X>();
1038 }
1039 
1040 template <typename X, class T>
1041 std::shared_ptr<X> qobject_pointer_cast(std::shared_ptr<T> &&src)
1042 {
1043     using element_type = typename std::shared_ptr<X>::element_type;
1044     auto castResult = qobject_cast<element_type *>(src.get());
1045     if (castResult) {
1046         // C++2a's move aliasing constructor will leave src empty.
1047         // Before C++2a we don't really know if the compiler has support for it.
1048         // The move aliasing constructor is the resolution for LWG2996,
1049         // which does not impose a feature-testing macro. So: clear src.
1050         return std::shared_ptr<X>(std::exchange(src, nullptr), castResult);
1051     }
1052     return std::shared_ptr<X>();
1053 }
1054 
1055 template <typename X, class T>
1056 std::shared_ptr<X> qSharedPointerObjectCast(const std::shared_ptr<T> &src)
1057 {
1058     return qobject_pointer_cast<X>(src);
1059 }
1060 
1061 template <typename X, class T>
1062 std::shared_ptr<X> qSharedPointerObjectCast(std::shared_ptr<T> &&src)
1063 {
1064     return qobject_pointer_cast<X>(std::move(src));
1065 }
1066 
1067 #endif
1068 
1069 template<typename T> Q_DECLARE_TYPEINFO_BODY(QWeakPointer<T>, Q_RELOCATABLE_TYPE);
1070 template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedPointer<T>, Q_RELOCATABLE_TYPE);
1071 
1072 
1073 QT_END_NAMESPACE
1074 
1075 #endif