Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-07 08:48:21

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