Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:07:36

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