Revision control
++ // Copyright (C) 2020 The Qt Company Ltd.
++ // Copyright (C) 2020 Intel Corporation.
++ // Copyright (C) 2019 Klarälvdalens Datakonsult AB.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++ // Qt-Security score:significant reason:default
++
++ #include "qsharedpointer.h"
++
++ // to be sure we aren't causing a namespace clash:
++ #include "qshareddata.h"
++
++ /*!
++ \class QSharedPointer
++ \inmodule QtCore
++ \brief The QSharedPointer class holds a strong reference to a shared pointer.
++ \since 4.5
++
++ \reentrant
++
++ \compares strong
++ \compareswith strong QSharedPointer<X> X* std::nullptr_t
++ Where X and T are compatible types, which means that they are either the same or one
++ is a base type of the other.
++ \endcompareswith
++
++ The QSharedPointer is an automatic, shared pointer in C++, where the
++ template parameter \a T specifies the type of the pointer being managed.
++ It behaves exactly like a normal pointer for normal purposes,
++ including respect for constness.
++
++ QSharedPointer will delete the pointer it is holding when it goes
++ out of scope, provided no other QSharedPointer objects are
++ referencing it.
++
++ A QSharedPointer object can be created from a normal pointer,
++ another QSharedPointer object or by promoting a
++ QWeakPointer object to a strong reference.
++
++ \section1 Thread-Safety
++
++ QSharedPointer and QWeakPointer are reentrant classes. This means that, in
++ general, a given QSharedPointer or QWeakPointer object \b{cannot} be
++ accessed by multiple threads at the same time without synchronization.
++
++ Different QSharedPointer and QWeakPointer objects can safely be accessed
++ by multiple threads at the same time. This includes the case where they
++ hold pointers to the same object; the reference counting mechanism
++ is atomic, and no manual synchronization is required.
++
++ It should be noted that, while the pointer value can be accessed in this
++ manner (that is, by multiple threads at the same time, without
++ synchronization), QSharedPointer and QWeakPointer provide no guarantee
++ about the object being pointed to. The specific thread-safety and
++ reentrancy rules for that object still apply.
++
++ \section1 Other Pointer Classes
++
++ Qt also provides two other pointer wrapper classes: QPointer and
++ QSharedDataPointer. They are incompatible with one another, since
++ each has its very different use case.
++
++ QSharedPointer holds a shared pointer by means of an external
++ reference count (i.e., a reference counter placed outside the
++ object). Like its name indicates, the pointer value is shared
++ among all instances of QSharedPointer and QWeakPointer. The
++ contents of the object pointed to by the pointer should not be
++ considered shared, however: there is only one object. For that
++ reason, QSharedPointer does not provide a way to detach or make
++ copies of the pointed object.
++
++ QSharedDataPointer, on the other hand, holds a pointer to shared
++ data (i.e., a class derived from QSharedData). It does so by means
++ of an internal reference count, placed in the QSharedData base
++ class. This class can, therefore, detach based on the type of
++ access made to the data being guarded: if it's a non-const access,
++ it creates a copy atomically for the operation to complete.
++
++ QExplicitlySharedDataPointer is a variant of QSharedDataPointer, except
++ that it only detaches if QExplicitlySharedDataPointer::detach() is
++ explicitly called (hence the name).
++
++ QScopedPointer simply holds a pointer to a heap allocated object and
++ deletes it in its destructor. This class is useful when an object needs to
++ be heap allocated and deleted, but no more. QScopedPointer is lightweight,
++ it makes no use of additional structure or reference counting.
++
++ Finally, QPointer holds a pointer to a QObject-derived object, but it
++ does so weakly. QWeakPointer has the same functionality, but its use for
++ that function is deprecated.
++
++ \section1 Optional Pointer Tracking
++
++ A feature of QSharedPointer that can be enabled at compile-time for
++ debugging purposes is a pointer tracking mechanism. When enabled,
++ QSharedPointer registers in a global set all the pointers that it tracks.
++ This allows one to catch mistakes like assigning the same pointer to two
++ QSharedPointer objects.
++
++ This function is enabled by defining the \tt{QT_SHAREDPOINTER_TRACK_POINTERS}
++ macro before including the QSharedPointer header.
++
++ It is safe to use this feature even with code compiled without the
++ feature. QSharedPointer will ensure that the pointer is removed from the
++ tracker even from code compiled without pointer tracking.
++
++ Note, however, that the pointer tracking feature has limitations on
++ multiple- or virtual-inheritance (that is, in cases where two different
++ pointer addresses can refer to the same object). In that case, if a
++ pointer is cast to a different type and its value changes,
++ QSharedPointer's pointer tracking mechanism may fail to detect that the
++ object being tracked is the same.
++
++ \omit
++ \section1 QSharedPointer internals
++
++ QSharedPointer has two "private" members: the pointer itself being tracked
++ and a d-pointer. Those members are private to the class, but QSharedPointer
++ is friends with QWeakPointer and other QSharedPointer with different
++ template arguments. (On some compilers, template friends are not supported,
++ so the members are technically public)
++
++ The reason for keeping the pointer value itself outside the d-pointer is
++ because of multiple inheritance needs. If you have two QSharedPointer
++ objects of different pointer types, but pointing to the same object in
++ memory, it could happen that the pointer values are different. The \tt
++ differentPointers autotest exemplifies this problem. The same thing could
++ happen in the case of virtual inheritance: a pointer of class matching
++ the virtual base has different address compared to the pointer of the
++ complete object. See the \tt virtualBaseDifferentPointers autotest for
++ this problem.
++
++ The d pointer is a pointer to QtSharedPointer::ExternalRefCountData, but it
++ always points to one of the two classes derived from ExternalRefCountData.
++
++ \section2 d-pointer
++ \section3 QtSharedPointer::ExternalRefCountData
++
++ It is basically a reference-counted reference-counter plus a pointer to the
++ function to be used to delete the pointer. It has three members: \tt
++ strongref, \tt weakref, and \tt destroyer. The strong reference counter is
++ controlling the lifetime of the object tracked by QSharedPointer. A
++ positive value indicates that the object is alive. It's also the number of
++ QSharedObject instances that are attached to this Data.
++
++ When the strong reference count decreases to zero, the object is deleted
++ (see below for information on custom deleters). The strong reference count
++ can also exceptionally be -1, indicating that there are no QSharedPointers
++ attached to an object, which is tracked too. The only case where this is
++ possible is that of QWeakPointers and QPointers tracking a QObject. Note
++ that QWeakPointers tracking a QObject is deprecated.
++
++ The weak reference count controls the lifetime of the d-pointer itself.
++ It can be thought of as an internal/intrusive reference count for
++ ExternalRefCountData itself. This count is equal to the number of
++ QSharedPointers and QWeakPointers that are tracking this object. In case
++ the object is a QObject being tracked by QPointer, this number is increased
++ by 1, since QObjectPrivate tracks it too.
++
++ The third member is a pointer to the function that is used to delete the
++ pointer being tracked. That happens when the destroy() function is called.
++
++ The size of this class is the size of the two atomic ints plus the size of
++ a pointer. On 32-bit architectures, that's 12 bytes, whereas on 64-bit ones
++ it's 16 bytes. There is no padding.
++
++ \section3 QtSharedPointer::ExternalRefCountWithCustomDeleter
++
++ This class derives from ExternalRefCountData and is a template class. As
++ template parameters, it has the type of the pointer being tracked (\tt T)
++ and a \tt Deleter, which is anything. It adds two fields to its parent
++ class, matching those template parameters: a member of type \tt Deleter and
++ a member of type \tt T*. Those members are actually inside a template
++ struct of type CustomDeleter, which is partially-specialized for normal
++ deletion. See below for more details on that.
++
++ The purpose of this class is to store the pointer to be deleted and the
++ deleter code along with the d-pointer. This allows the last strong
++ reference to call any arbitrary function that disposes of the object. For
++ example, this allows calling QObject::deleteLater() on a given object.
++ The pointer to the object is kept here because it needs to match the actual
++ deleter function's parameters, regardless of what template argument the
++ last QSharedPointer instance had.
++
++ This class is never instantiated directly: the constructors and
++ destructor are deleted. Only the create() function
++ may be called to return an object of this type. See below for construction
++ details.
++
++ The size of this class depends on the size of \tt Deleter. If it's an empty
++ functor (i.e., no members), ABIs generally assign it the size of 1. But
++ given that it's followed by a pointer, padding bytes may be inserted so
++ that the alignment of the class and of the pointer are correct. In that
++ case, the size of this class is 12+4+4 = 20 bytes on 32-bit architectures,
++ or 16+8+8 = 40 bytes on 64-bit architectures. If \tt Deleter is a function
++ pointer, the size should be the same as the empty structure case. If \tt
++ Deleter is a pointer to a member function (PMF), the size will be bigger
++ and will depend on the ABI. For architectures using the Itanium C++ ABI, a
++ PMF is twice the size of a normal pointer. In that case, the size of this
++ structure will be 12+8+4 = 24 bytes on 32-bit architectures, 16+16+8 = 40
++ bytes on 64-bit ones.
++
++ If the deleter was not specified when creating the QSharedPointer object
++ (i.e., if a standard \tt delete call is expected), then there's an
++ optimization that avoids the need to store another function pointer in
++ ExternalRefCountWithCustomDeleter. Instead, a template specialization makes
++ a direct delete call. The size of the structure, in this case, is 12+4 = 16
++ bytes on 32-bit architectures, 16+8 = 24 bytes on 64-bit ones.
++
++ \section3 QtSharedPointer::ExternalRefCountWithContiguousData
++
++ This class also derives from ExternalRefCountData and it is
++ also a template class. The template parameter is the type \tt T of the
++ class which QSharedPointer tracks. It adds only one member to its parent,
++ which is of type \tt T (the actual type, not a pointer to it).
++
++ The purpose of this class is to lay the \tt T object out next to the
++ reference counts, saving one memory allocation per shared pointer. This
++ is particularly interesting for small \tt T or for the cases when there
++ are few if any QWeakPointer tracking the object. This class exists to
++ implement the QSharedPointer::create() call.
++
++ Like ExternalRefCountWithCustomDeleter, this class is never instantiated
++ directly. This class also provides a create() member that returns the
++ pointer, and deletes its constructors and destructor.
++
++ The size of this class depends on the size of \tt T.
++
++ \section3 Instantiating ExternalRefCountWithCustomDeleter and ExternalRefCountWithContiguousData
++
++ Like explained above, these classes have private constructors. Moreover,
++ they are not defined anywhere, so trying to call \tt{new ClassType} would
++ result in a compilation or linker error. Instead, these classes must be
++ constructed via their create() methods.
++
++ Instead of instantiating the class by the normal way, the create() method
++ calls \tt{operator new} directly with the size of the class, then calls
++ the parent class's constructor only (that is, ExternalRefCountData's constructor).
++ This ensures that the inherited members are initialised properly.
++
++ After initialising the base class, the
++ ExternalRefCountWithCustomDeleter::create() function initialises the new
++ members directly, by using the placement \tt{operator new}. In the case
++ of the ExternalRefCountWithContiguousData::create() function, the address
++ to the still-uninitialised \tt T member is saved for the callee to use.
++ The member is only initialised in QSharedPointer::create(), so that we
++ avoid having many variants of the internal functions according to the
++ arguments in use for calling the constructor.
++
++ When initialising the parent class, the create() functions pass the
++ address of the static deleter() member function. That is, when the
++ destroy() function is called by QSharedPointer, the deleter() functions
++ are called instead. These functions static_cast the ExternalRefCountData*
++ parameter to their own type and execute their deletion: for the
++ ExternalRefCountWithCustomDeleter::deleter() case, it runs the user's
++ custom deleter, then destroys the deleter; for
++ ExternalRefCountWithContiguousData::deleter, it simply calls the \tt T
++ destructor directly.
++
++ Only one non-inline function is required per template, which is
++ the deleter() static member. All the other functions can be inlined.
++ What's more, the address of deleter() is calculated only in code, which
++ can be resolved at link-time if the linker can determine that the
++ function lies in the current application or library module (since these
++ classes are not exported, that is the case for Windows or for builds with
++ \tt{-fvisibility=hidden}).
++
++ \section3 Modifications due to pointer-tracking
++
++ To ensure that pointers created with pointer-tracking enabled get
++ un-tracked when destroyed, even if destroyed by code compiled without the
++ feature, QSharedPointer modifies slightly the instructions of the
++ previous sections.
++
++ When ExternalRefCountWithCustomDeleter or
++ ExternalRefCountWithContiguousData are used, their create() functions
++ will set the ExternalRefCountData::destroyer function
++ pointer to safetyCheckDeleter() instead. These static member functions
++ simply call internalSafetyCheckRemove() before passing control to the
++ normal deleter() function.
++
++ If neither custom deleter nor QSharedPointer::create() are used, then
++ QSharedPointer uses a custom deleter of its own: the normalDeleter()
++ function, which simply calls \tt delete. By using a custom deleter, the
++ safetyCheckDeleter() procedure described above kicks in.
++
++ \endomit
++
++ \sa QSharedDataPointer, QWeakPointer, QScopedPointer, QEnableSharedFromThis
++ */
++
++ /*!
++ \class QWeakPointer
++ \inmodule QtCore
++ \brief The QWeakPointer class holds a weak reference to a shared pointer.
++ \since 4.5
++ \reentrant
++
++ The QWeakPointer is an automatic weak reference to a
++ pointer in C++, where the template parameter \a T specifies the type
++ of the pointer being tracked. It cannot be used to dereference the
++ pointer directly, but it can be used to verify if the pointer has been
++ deleted or not in another context.
++
++ QWeakPointer objects can only be created by assignment from a
++ QSharedPointer.
++
++ It's important to note that QWeakPointer provides no automatic casting
++ operators to prevent mistakes from happening. Even though QWeakPointer
++ tracks a pointer, it should not be considered a pointer itself, since it
++ doesn't guarantee that the pointed object remains valid.
++
++ Therefore, to access the pointer that QWeakPointer is tracking, you must
++ first promote it to QSharedPointer and verify if the resulting object is
++ null or not. QSharedPointer guarantees that the object isn't deleted, so
++ if you obtain a non-null object, you may use the pointer. See
++ QWeakPointer::toStrongRef() for an example.
++
++ \omit
++ \section1 QWeakPointer internals
++
++ QWeakPointer shares most of its internal functionality with
++ \l{QSharedPointer#qsharedpointer-internals}{QSharedPointer}, so see that
++ class's internal documentation for more information.
++
++ QWeakPointer requires an external reference counter in order to operate.
++ Therefore, it is incompatible by design with \l QSharedData-derived
++ classes.
++
++ It has a special QObject constructor, which works by calling
++ QtSharedPointer::ExternalRefCountData::getAndRef, which retrieves the
++ d-pointer from QObjectPrivate. If one isn't set yet, that function
++ creates the d-pointer and atomically sets it.
++
++ If getAndRef needs to create a d-pointer, it sets the strongref to -1,
++ indicating that the QObject is not shared: QWeakPointer is used only to
++ determine whether the QObject has been deleted. In that case, it cannot
++ be upgraded to QSharedPointer (see the previous section).
++
++ \endomit
++
++ \sa QSharedPointer, QScopedPointer
++ */
++
++ /*!
++ \class QEnableSharedFromThis
++ \inmodule QtCore
++ \brief A base class that allows obtaining a QSharedPointer for an object already managed by a shared pointer.
++ \since 5.4
++
++ You can inherit this class when you need to create a QSharedPointer
++ from any instance of a class; for instance, from within the
++ object itself. The template parameter \a T specifies the type of the
++ class that inherits from QEnableSharedFromThis. The key point is that
++ the technique of just returning QSharedPointer<T>(this) cannot be used,
++ because this winds up creating multiple distinct QSharedPointer objects
++ with separate reference counts. For this reason you must never
++ create more than one QSharedPointer from the same raw pointer.
++
++ QEnableSharedFromThis defines two member functions called
++ sharedFromThis() that return a QSharedPointer<T> and
++ QSharedPointer<const T>, depending on constness, to \c this:
++
++ \snippet code/src_corelib_tools_qsharedpointer.cpp 0
++
++ It is also possible to get a shared pointer from an object outside of
++ the class itself. This is especially useful in code that provides an
++ interface to scripts, where it is currently not possible to use shared
++ pointers. For example:
++
++ \snippet code/src_corelib_tools_qsharedpointer.cpp 1
++ */
++
++ /*!
++ \fn template <class T> QSharedPointer<T>::QSharedPointer()
++
++ Creates a QSharedPointer that is null (the object is holding
++ a reference to \nullptr).
++ */
++
++ /*!
++ \fn template <class T> QSharedPointer<T>::~QSharedPointer()
++
++ Destroys this QSharedPointer object. If it is the last reference to
++ the pointer stored, this will delete the pointer as well.
++ */
++
++ /*!
++ \fn template <class T> template <typename X> QSharedPointer<T>::QSharedPointer(X *ptr)
++
++ Creates a QSharedPointer that points to \a ptr. The pointer \a ptr
++ becomes managed by this QSharedPointer and must not be passed to
++ another QSharedPointer object or deleted outside this object.
++
++ Since Qt 5.8, when the last reference to this QSharedPointer gets
++ destroyed, \a ptr will be deleted by calling \c X's destructor (even if \c
++ X is not the same as QSharedPointer's template parameter \c T). Previously,
++ the destructor for \c T was called.
++ */
++
++ /*!
++ \fn template <class T> template <typename X, typename Deleter> QSharedPointer<T>::QSharedPointer(X *ptr, Deleter d)
++
++ Creates a QSharedPointer that points to \a ptr. The pointer \a ptr
++ becomes managed by this QSharedPointer and must not be passed to
++ another QSharedPointer object or deleted outside this object.
++
++ The deleter parameter \a d specifies the custom deleter for this
++ object. The custom deleter is called, instead of the operator delete(),
++ when the strong reference count drops to 0. This is useful,
++ for instance, for calling \l {QObject::}{deleteLater()} on a QObject instead:
++
++ \snippet code/src_corelib_tools_qsharedpointer.cpp 2
++
++ Note that the custom deleter function will be called with a pointer to type
++ \c X, even if the QSharedPointer template parameter \c T is not the same.
++
++ It is also possible to specify a member function directly, as in:
++ \snippet code/src_corelib_tools_qsharedpointer.cpp 3
++
++ \sa clear()
++ */
++
++ /*!
++ \fn template <class T> QSharedPointer<T>::QSharedPointer(std::nullptr_t)
++ \since 5.8
++
++ Creates a QSharedPointer that is null. This is equivalent to the
++ QSharedPointer default constructor.
++ */
++
++ /*!
++ \fn template <class T> template <typename Deleter> QSharedPointer<T>::QSharedPointer(std::nullptr_t, Deleter d)
++ \since 5.8
++
++ Creates a QSharedPointer that is null. This is equivalent to the
++ QSharedPointer default constructor.
++
++ The deleter parameter \a d specifies the custom deleter for this
++ object. The custom deleter is called, instead of the operator
++ delete(), when the strong reference count drops to 0.
++ */
++
++ /*!
++ \fn template <class T> QSharedPointer<T>::QSharedPointer(const QSharedPointer<T> &other)
++
++ Creates a QSharedPointer object that shares \a other's pointer.
++
++ If \tt T is a derived type of the template parameter of this class,
++ QSharedPointer will perform an automatic cast. Otherwise, you will
++ get a compiler error.
++ */
++
++ /*!
++ \fn template <class T> QSharedPointer<T>::QSharedPointer(QSharedPointer &&other)
++
++ Move-constructs a QSharedPointer instance, making it point at the same
++ object that \a other was pointing to.
++
++ \since 5.4
++ */
++
++ /*!
++ \fn template <class T> QSharedPointer<T>::operator=(QSharedPointer &&other)
++
++ Move-assigns \a other to this QSharedPointer instance.
++
++ \since 5.0
++ */
++
++ /*!
++ \fn template <class T> template <class X> QSharedPointer<T>::QSharedPointer(QSharedPointer<X> &&other)
++
++ Move-constructs a QSharedPointer instance, making it point at the same
++ object that \a other was pointing to.
++
++ \constraints \c{X*} implicitly converts to \c{T*}.
++
++ \since 5.6
++ */
++
++ /*!
++ \fn template <class T> template <class X> QSharedPointer<T>::operator=(QSharedPointer<X> &&other)
++
++ Move-assigns \a other to this QSharedPointer instance.
++
++ \constraints \c{X*} implicitly converts to \c{T*}.
++
++ \since 5.6
++ */
++
++ /*!
++ \fn template <class T> QSharedPointer<T>::QSharedPointer(const QWeakPointer<T> &other)
++
++ Creates a QSharedPointer by promoting the weak reference \a other
++ to strong reference and sharing its pointer.
++
++ If \tt T is a derived type of the template parameter of this
++ class, QSharedPointer will perform an automatic cast. Otherwise,
++ you will get a compiler error.
++
++ \sa QWeakPointer::toStrongRef()
++ */
++
++ /*!
++ \fn template <class T> QSharedPointer &QSharedPointer<T>::operator=(const QSharedPointer<T> &other)
++
++ Makes this object share \a other's pointer. The current pointer
++ reference is discarded and, if it was the last, the pointer will
++ be deleted.
++
++ If \tt T is a derived type of the template parameter of this
++ class, QSharedPointer will perform an automatic cast. Otherwise,
++ you will get a compiler error.
++ */
++
++ /*!
++ \fn template <class T> QSharedPointer &QSharedPointer<T>::operator=(const QWeakPointer<T> &other)
++
++ Promotes \a other to a strong reference and makes this object
++ share a reference to the pointer referenced by it. The current pointer
++ reference is discarded and, if it was the last, the pointer will
++ be deleted.
++
++ If \tt T is a derived type of the template parameter of this
++ class, QSharedPointer will perform an automatic cast. Otherwise,
++ you will get a compiler error.
++ */
++
++ /*!
++ \fn template <class T> void QSharedPointer<T>::swap(QSharedPointer<T> &other);
++ \since 5.3
++ \memberswap{shared pointer instance}
++ */
++
++ /*!
++ \fn template <class T> T *QSharedPointer<T>::data() const
++
++ Returns the value of the pointer referenced by this object.
++
++ Note: do not delete the pointer returned by this function or pass
++ it to another function that could delete it, including creating
++ QSharedPointer or QWeakPointer objects.
++ */
++
++ /*!
++ \fn template <class T> T *QSharedPointer<T>::get() const
++ \since 5.11
++
++ Same as data().
++
++ This function is provided for API compatibility with \c{std::shared_ptr}.
++ */
++
++ /*!
++ \fn template <class T> T &QSharedPointer<T>::operator *() const
++
++ Provides access to the shared pointer's members.
++
++ If the contained pointer is \nullptr, behavior is undefined.
++ \sa isNull()
++ */
++
++ /*!
++ \fn template <class T> T *QSharedPointer<T>::operator ->() const
++
++ Provides access to the shared pointer's members.
++
++ If the contained pointer is \nullptr, behavior is undefined.
++ \sa isNull()
++ */
++
++ /*!
++ \fn template <class T> bool QSharedPointer<T>::isNull() const
++
++ Returns \c true if this object refers to \nullptr.
++ */
++
++ /*!
++ \fn template <class T> QSharedPointer<T>::operator bool() const
++
++ Returns \c true if the contained pointer is not \nullptr.
++ This function is suitable for use in \tt if-constructs, like:
++
++ \snippet code/src_corelib_tools_qsharedpointer.cpp 4
++
++ \sa isNull()
++ */
++
++ /*!
++ \fn template <class T> bool QSharedPointer<T>::operator !() const
++
++ Returns \c true if this object refers to \nullptr.
++ This function is suitable for use in \tt if-constructs, like:
++
++ \snippet code/src_corelib_tools_qsharedpointer.cpp 5
++
++ \sa isNull()
++ */
++
++ /*
++ //! [cast-overload-for-this]
++ The returned QSharedPointer shares ownership with the same set of
++ shared owners as \c {*this}.
++
++ This function \l {reset()}{resets} \c {*this} to \nullptr on success.
++ //! [cast-overload-for-this]
++
++ //! [cast-overload-for-arg]
++ The returned QSharedPointer shares ownership with the same set of
++ shared owners as \a {\1}.
++
++ This function \l {reset()}{resets} \a {\1} to \nullptr on success.
++ //! [cast-overload-for-arg]
++ */
++
++ /*!
++ \fn template <class T> template <class X> QSharedPointer<X> QSharedPointer<T>::staticCast() const &
++
++ Performs a static cast from this pointer's type to \tt X and returns
++ a QSharedPointer that shares the reference. This function can be
++ used for up- and for down-casting, but is more useful for
++ up-casting.
++
++ Note: the template type \c X must have the same const and volatile
++ qualifiers as the template of this object, or the cast will
++ fail. Use constCast() if you need to drop those qualifiers.
++
++ \sa dynamicCast(), constCast(), qSharedPointerStaticCast()
++ */
++
++ /*!
++ \fn template <class T> template <class X> QSharedPointer<X> QSharedPointer<T>::staticCast() &&
++ \since 6.9
++ \overload staticCast()
++
++ \include qsharedpointer.cpp {cast-overload-for-this}
++
++ \sa dynamicCast(), constCast(), qSharedPointerStaticCast()
++ */
++
++ /*!
++ \fn template <class T> template <class X> QSharedPointer<X> QSharedPointer<T>::dynamicCast() const &
++
++ Performs a dynamic cast from this pointer's type to \tt X and
++ returns a QSharedPointer that shares the reference. If this
++ function is used to up-cast, then QSharedPointer will perform a \tt
++ dynamic_cast, which means that if the object being pointed by this
++ QSharedPointer is not of type \tt X, the returned object will be
++ null.
++
++ Note: the template type \c X must have the same const and volatile
++ qualifiers as the template of this object, or the cast will
++ fail. Use constCast() if you need to drop those qualifiers.
++
++ \sa qSharedPointerDynamicCast()
++ */
++
++ /*!
++ \fn template <class T> template <class X> QSharedPointer<X> QSharedPointer<T>::dynamicCast() &&
++ \since 6.9
++ \overload dynamicCast()
++
++ \include qsharedpointer.cpp {cast-overload-for-this}
++
++ \sa qSharedPointerDynamicCast()
++ */
++
++ /*!
++ \fn template <class T> template <class X> QSharedPointer<X> QSharedPointer<T>::constCast() const &
++
++ Performs a \tt const_cast from this pointer's type to \tt X and returns
++ a QSharedPointer that shares the reference. This function can be
++ used for up- and for down-casting, but is more useful for
++ up-casting.
++
++ \sa isNull(), qSharedPointerConstCast()
++ */
++
++ /*!
++ \fn template <class T> template <class X> QSharedPointer<X> QSharedPointer<T>::constCast() &&
++ \since 6.9
++ \overload constCast()
++
++ \include qsharedpointer.cpp {cast-overload-for-this}
++
++ \sa isNull(), qSharedPointerConstCast()
++ */
++
++ /*!
++ \fn template <class T> template <class X> QSharedPointer<X> QSharedPointer<T>::objectCast() const &
++ \since 4.6
++
++ Performs a \l qobject_cast() from this pointer's type to \tt X and
++ returns a QSharedPointer that shares the reference. If this
++ function is used to up-cast, then QSharedPointer will perform a \tt
++ qobject_cast, which means that if the object being pointed by this
++ QSharedPointer is not of type \tt X, the returned object will be
++ null.
++
++ Note: the template type \c X must have the same const and volatile
++ qualifiers as the template of this object, or the cast will
++ fail. Use constCast() if you need to drop those qualifiers.
++
++ \sa qSharedPointerObjectCast()
++ */
++
++ /*!
++ \fn template <class T> template <class X> QSharedPointer<X> QSharedPointer<T>::objectCast() &&
++ \since 6.9
++ \overload objectCast()
++
++ \include qsharedpointer.cpp {cast-overload-for-this}
++
++ \sa qSharedPointerObjectCast()
++ */
++
++ /*!
++ \fn template <class T> template <typename... Args> QSharedPointer<T> QSharedPointer<T>::create(Args &&... args)
++ \overload
++ \since 5.1
++
++ Creates a QSharedPointer object and allocates a new item of type \tt T. The
++ QSharedPointer internals and the object are allocated in one single memory
++ allocation, which could help reduce memory fragmentation in a long-running
++ application.
++
++ This function will attempt to call a constructor for type \tt T that can
++ accept all the arguments passed (\a args). Arguments will be perfectly-forwarded.
++ */
++
++ /*!
++ \fn template <class T> QWeakPointer<T> QSharedPointer<T>::toWeakRef() const
++
++ Returns a weak reference object that shares the pointer referenced
++ by this object.
++
++ \sa QWeakPointer::QWeakPointer()
++ */
++
++ /*!
++ \fn template <class T> void QSharedPointer<T>::clear()
++
++ Clears this QSharedPointer object, dropping the reference that it
++ may have had to the pointer. If this was the last reference, then
++ the pointer itself will be deleted.
++ */
++
++ /*!
++ \fn template <class T> void QSharedPointer<T>::reset()
++ \since 5.0
++
++ Same as clear(). For std::shared_ptr compatibility.
++ */
++
++ /*!
++ \fn template <class T> void QSharedPointer<T>::reset(T *t)
++ \since 5.0
++
++ Resets this QSharedPointer object to point to \a t
++ instead. Equivalent to:
++ \snippet code/src_corelib_tools_qsharedpointer.cpp 6
++ */
++
++ /*!
++ \fn template <class T> template <typename Deleter> void QSharedPointer<T>::reset(T *t, Deleter deleter)
++ \since 5.0
++
++ Resets this QSharedPointer object to point to \a t
++ instead, with the Deleter \a deleter. Equivalent to:
++ \snippet code/src_corelib_tools_qsharedpointer.cpp 7
++ */
++
++ /*!
++ \fn template <class T> template <class X> bool QSharedPointer<T>::owner_before(const QSharedPointer<X> &other) const noexcept
++ \fn template <class T> template <class X> bool QSharedPointer<T>::owner_before(const QWeakPointer<X> &other) const noexcept
++ \fn template <class T> template <class X> bool QWeakPointer<T>::owner_before(const QSharedPointer<X> &other) const noexcept
++ \fn template <class T> template <class X> bool QWeakPointer<T>::owner_before(const QWeakPointer<X> &other) const noexcept
++ \since 6.7
++
++ Returns \c true if and only if this smart pointer precedes \a other
++ in an implementation-defined owner-based ordering. The ordering is such
++ that two smart pointers are considered equivalent if they are both
++ empty or if they both own the same object (even if their apparent type
++ and pointer are different).
++
++ \sa owner_equal
++ */
++
++ /*!
++ \fn template <class T> template <class X> bool QSharedPointer<T>::owner_equal(const QSharedPointer<X> &other) const noexcept
++ \fn template <class T> template <class X> bool QSharedPointer<T>::owner_equal(const QWeakPointer<X> &other) const noexcept
++ \fn template <class T> template <class X> bool QWeakPointer<T>::owner_equal(const QSharedPointer<X> &other) const noexcept
++ \fn template <class T> template <class X> bool QWeakPointer<T>::owner_equal(const QWeakPointer<X> &other) const noexcept
++
++ \since 6.7
++
++ Returns \c true if and only if this smart pointer and \a other
++ share ownership.
++
++ \sa owner_before, owner_hash
++ */
++
++ /*!
++ \fn template <class T> size_t QSharedPointer<T>::owner_hash() const noexcept
++ \fn template <class T> size_t QWeakPointer<T>::owner_hash() const noexcept
++
++ \since 6.7
++
++ Returns a owner-based hash value for this smart pointer object.
++ Smart pointers that compare equal (as per \c{owner_equal}) will
++ have an identical owner-based hash.
++
++ \sa owner_equal
++ */
++
++ /*!
++ \fn template <class T> QWeakPointer<T>::QWeakPointer()
++
++ Creates a QWeakPointer that points to nothing.
++ */
++
++ /*!
++ \fn template <class T> QWeakPointer<T>::~QWeakPointer()
++
++ Destroys this QWeakPointer object. The pointer referenced
++ by this object will not be deleted.
++ */
++
++ /*!
++ \fn template <class T> QWeakPointer<T>::QWeakPointer(const QWeakPointer<T> &other)
++
++ Creates a QWeakPointer that holds a weak reference to the
++ pointer referenced by \a other.
++
++ If \tt T is a derived type of the template parameter of this
++ class, QWeakPointer will perform an automatic cast. Otherwise,
++ you will get a compiler error.
++ */
++
++ /*!
++ \fn template <class T> QWeakPointer<T>::QWeakPointer(const QSharedPointer<T> &other)
++
++ Creates a QWeakPointer that holds a weak reference to the
++ pointer referenced by \a other.
++
++ If \tt T is a derived type of the template parameter of this
++ class, QWeakPointer will perform an automatic cast. Otherwise,
++ you will get a compiler error.
++ */
++
++ /*!
++ \fn template <class T> QWeakPointer &QWeakPointer<T>::operator=(const QWeakPointer<T> &other)
++
++ Makes this object share \a other's pointer. The current pointer
++ reference is discarded but is not deleted.
++
++ If \tt T is a derived type of the template parameter of this
++ class, QWeakPointer will perform an automatic cast. Otherwise,
++ you will get a compiler error.
++ */
++
++ /*!
++ \fn template <class T> QWeakPointer &QWeakPointer<T>::operator=(const QSharedPointer<T> &other)
++
++ Makes this object share \a other's pointer. The current pointer
++ reference is discarded but is not deleted.
++
++ If \tt T is a derived type of the template parameter of this
++ class, QWeakPointer will perform an automatic cast. Otherwise,
++ you will get a compiler error.
++ */
++
++ /*!
++ \fn template <class T> void QWeakPointer<T>::swap(QWeakPointer<T> &other)
++ \since 5.4
++ \memberswap{weak pointer instance}
++ */
++
++ /*!
++ \fn template <class T> bool QWeakPointer<T>::isNull() const
++
++ Returns \c true if this object refers to \nullptr.
++
++ Note that, due to the nature of weak references, the pointer that
++ QWeakPointer references can become \nullptr at any moment, so
++ the value returned from this function can change from false to
++ true from one call to the next.
++ */
++
++ /*!
++ \fn template <class T> QWeakPointer<T>::operator bool() const
++
++ Returns \c true if the contained pointer is not \nullptr.
++ This function is suitable for use in \tt if-constructs, like:
++
++ \snippet code/src_corelib_tools_qsharedpointer.cpp 8
++
++ Note that, due to the nature of weak references, the pointer that
++ QWeakPointer references can become \nullptr at any moment, so
++ the value returned from this function can change from true to
++ false from one call to the next.
++
++ \sa isNull()
++ */
++
++ /*!
++ \fn template <class T> bool QWeakPointer<T>::operator !() const
++
++ Returns \c true if this object refers to \nullptr.
++ This function is suitable for use in \tt if-constructs, like:
++
++ \snippet code/src_corelib_tools_qsharedpointer.cpp 9
++
++ Note that, due to the nature of weak references, the pointer that
++ QWeakPointer references can become \nullptr at any moment, so
++ the value returned from this function can change from false to
++ true from one call to the next.
++
++ \sa isNull()
++ */
++
++ /*!
++ \fn template <class T> QSharedPointer<T> QWeakPointer<T>::toStrongRef() const
++
++ Promotes this weak reference to a strong one and returns a
++ QSharedPointer object holding that reference. When promoting to
++ QSharedPointer, this function verifies if the object has been deleted
++ already or not. If it hasn't, this function increases the reference
++ count to the shared object, thus ensuring that it will not get
++ deleted.
++
++ Since this function can fail to obtain a valid strong reference to the
++ shared object, you should always verify if the conversion succeeded,
++ by calling QSharedPointer::isNull() on the returned object.
++
++ For example, the following code promotes a QWeakPointer that was held
++ to a strong reference and, if it succeeded, it prints the value of the
++ integer that was held:
++
++ \snippet code/src_corelib_tools_qsharedpointer.cpp 12
++
++ \sa QSharedPointer::QSharedPointer()
++ */
++
++ /*!
++ \fn template <class T> QSharedPointer<T> QWeakPointer<T>::lock() const
++ \since 5.4
++
++ Same as toStrongRef().
++
++ This function is provided for API compatibility with std::weak_ptr.
++ */
++
++ /*!
++ \fn template <class T> void QWeakPointer<T>::clear()
++
++ Clears this QWeakPointer object, dropping the reference that it
++ may have had to the pointer.
++ */
++
++ /*!
++ \fn template <class T> QSharedPointer<T> QEnableSharedFromThis<T>::sharedFromThis()
++ \since 5.4
++
++ If \c this (that is, the subclass instance invoking this method) is being
++ managed by a QSharedPointer, returns a shared pointer instance pointing to
++ \c this; otherwise returns a null QSharedPointer.
++ */
++
++ /*!
++ \fn template <class T> QSharedPointer<const T> QEnableSharedFromThis<T>::sharedFromThis() const
++ \overload
++ \since 5.4
++
++ Const overload of sharedFromThis().
++ */
++
++ /*!
++ \fn template <class T> qHash(const QSharedPointer<T> &key, size_t seed)
++ \qhashold{QSharedPointer}
++ \since 5.0
++ */
++
++ /*!
++ \fn template<class T, class X> bool operator==(const QSharedPointer<T> &lhs, const QSharedPointer<X> &rhs)
++ \relates QSharedPointer
++
++ Returns \c true if \a lhs and \a rhs refer to the same pointer.
++
++ //! [qsharedpointer-different-template-parameters]
++ If \a rhs's template parameter is different from \a lhs's,
++ QSharedPointer first needs to ensure that they are compatible types.
++ It will attempt to perform an automatic \tt static_cast to convert
++ the types \tt T and \tt X to their composite pointer type.
++ If \a rhs's template parameter is not a base or a derived type from
++ \a lhs's, you will get a compiler error.
++ //! [qsharedpointer-different-template-parameters]
++ */
++
++ /*!
++ \fn template<class T, class X> bool operator!=(const QSharedPointer<T> &lhs, const QSharedPointer<X> &rhs)
++ \relates QSharedPointer
++
++ Returns \c true if \a lhs and \a rhs refer to distinct pointers.
++
++ \include qsharedpointer.cpp qsharedpointer-different-template-parameters
++ */
++
++ /*!
++ \fn template<class T, class X> bool operator==(const QSharedPointer<T> &lhs, const X *rhs)
++ \relates QSharedPointer
++
++ Returns \c true if \a lhs and \a rhs refer to the same pointer.
++
++ \include qsharedpointer.cpp qsharedpointer-different-template-parameters
++ */
++
++ /*!
++ \fn template<class T, class X> bool operator!=(const QSharedPointer<T> &lhs, const X *rhs)
++ \relates QSharedPointer
++
++ Returns \c true if \a lhs and \a rhs refer to distinct pointers.
++
++ \include qsharedpointer.cpp qsharedpointer-different-template-parameters
++ */
++
++ /*!
++ \fn template<class T, class X> bool operator==(const T *lhs, const QSharedPointer<X> &rhs)
++ \relates QSharedPointer
++
++ Returns \c true if the pointer \a lhs is the
++ same pointer as that referenced by \a rhs.
++
++ \include qsharedpointer.cpp qsharedpointer-different-template-parameters
++ */
++
++ /*!
++ \fn template<class T, class X> bool operator!=(const T *lhs, const QSharedPointer<X> &rhs)
++ \relates QSharedPointer
++
++ Returns \c true if the pointer \a lhs is not the
++ same pointer as that referenced by \a rhs.
++
++ \include qsharedpointer.cpp qsharedpointer-different-template-parameters
++ */
++
++ /*!
++ \fn template<class T, class X> bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
++ \relates QWeakPointer
++
++ Returns \c true if \a ptr1 and \a ptr2 refer to the same pointer.
++
++ If \a ptr2's template parameter is different from \a ptr1's,
++ QSharedPointer will attempt to perform an automatic \tt static_cast
++ to ensure that the pointers being compared are equal. If \a ptr2's
++ template parameter is not a base or a derived type from
++ \a ptr1's, you will get a compiler error.
++ */
++
++ /*!
++ \fn template<class T, class X> bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
++ \relates QWeakPointer
++
++ Returns \c true if \a ptr1 and \a ptr2 refer to distinct pointers.
++
++ If \a ptr2's template parameter is different from \a ptr1's,
++ QSharedPointer will attempt to perform an automatic \tt static_cast
++ to ensure that the pointers being compared are equal. If \a ptr2's
++ template parameter is not a base or a derived type from
++ \a ptr1's, you will get a compiler error.
++ */
++
++ /*!
++ \fn template<class T, class X> bool operator==(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
++ \relates QWeakPointer
++
++ Returns \c true if \a ptr1 and \a ptr2 refer to the same pointer.
++
++ If \a ptr2's template parameter is different from \a ptr1's,
++ QSharedPointer will attempt to perform an automatic \tt static_cast
++ to ensure that the pointers being compared are equal. If \a ptr2's
++ template parameter is not a base or a derived type from
++ \a ptr1's, you will get a compiler error.
++ */
++
++ /*!
++ \fn template <class T> bool operator==(const QSharedPointer<T> &lhs, std::nullptr_t)
++ \relates QSharedPointer
++ \since 5.8
++
++ Returns \c true if \a lhs refers to \nullptr.
++
++ \sa QSharedPointer::isNull()
++ */
++
++ /*!
++ \fn template <class T> bool operator==(std::nullptr_t, const QSharedPointer<T> &rhs)
++ \relates QSharedPointer
++ \since 5.8
++
++ Returns \c true if \a rhs refers to \nullptr.
++
++ \sa QSharedPointer::isNull()
++ */
++
++ /*!
++ \fn template <class T> bool operator!=(const QSharedPointer<T> &lhs, std::nullptr_t)
++ \relates QSharedPointer
++ \since 5.8
++
++ Returns \c true if \a lhs refers to a valid (i.e. non-null) pointer.
++
++ \sa QSharedPointer::isNull()
++ */
++
++ /*!
++ \fn template <class T> bool operator!=(std::nullptr_t, const QSharedPointer<T> &rhs)
++ \relates QSharedPointer
++ \since 5.8
++
++ Returns \c true if \a rhs refers to a valid (i.e. non-null) pointer.
++
++ \sa QSharedPointer::isNull()
++ */
++
++ /*!
++ \fn template <class T> bool operator==(const QWeakPointer<T> &lhs, std::nullptr_t)
++ \relates QWeakPointer
++ \since 5.8
++
++ Returns \c true if \a lhs refers to \nullptr.
++
++ \sa QWeakPointer::isNull()
++ */
++
++ /*!
++ \fn template <class T> bool operator==(std::nullptr_t, const QWeakPointer<T> &rhs)
++ \relates QWeakPointer
++ \since 5.8
++
++ Returns \c true if \a rhs refers to \nullptr.
++
++ \sa QWeakPointer::isNull()
++ */
++
++ /*!
++ \fn template <class T> bool operator!=(const QWeakPointer<T> &lhs, std::nullptr_t)
++ \relates QWeakPointer
++ \since 5.8
++
++ Returns \c true if \a lhs refers to a valid (i.e. non-null) pointer.
++
++ \sa QWeakPointer::isNull()
++ */
++
++ /*!
++ \fn template <class T> bool operator!=(std::nullptr_t, const QWeakPointer<T> &rhs)
++ \relates QWeakPointer
++ \since 5.8
++
++ Returns \c true if \a rhs refers to a valid (i.e. non-null) pointer.
++
++ \sa QWeakPointer::isNull()
++ */
++
++ /*!
++ \fn template<class T, class X> bool operator!=(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
++ \relates QWeakPointer
++
++ Returns \c true if \a ptr1 and \a ptr2 refer to distinct pointers.
++
++ If \a ptr2's template parameter is different from \a ptr1's,
++ QSharedPointer will attempt to perform an automatic \tt static_cast
++ to ensure that the pointers being compared are equal. If \a ptr2's
++ template parameter is not a base or a derived type from
++ \a ptr1's, you will get a compiler error.
++ */
++
++ /*!
++ \fn template <class X, class T> QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &other)
++ \relates QSharedPointer
++
++ Returns a shared pointer to the pointer held by \a other, cast to
++ type \tt X. The types \tt T and \tt X must belong to one
++ hierarchy for the \tt static_cast to succeed.
++
++ Note that \tt X must have the same cv-qualifiers (\tt const and
++ \tt volatile) that \tt T has, or the code will fail to
++ compile. Use qSharedPointerConstCast to cast away the constness.
++
++ \sa QSharedPointer::staticCast(), qSharedPointerDynamicCast(), qSharedPointerConstCast()
++ */
++
++ /*!
++ \fn template <class X, class T> QSharedPointer<X> qSharedPointerCast(QSharedPointer<T> &&other)
++ \relates QSharedPointer
++ \since 6.9
++ \overload qSharedPointerCast(const QSharedPointer<T> &other)
++
++ \include qsharedpointer.cpp {cast-overload-for-arg} {other}
++
++ \sa QSharedPointer::staticCast(), qSharedPointerDynamicCast(), qSharedPointerConstCast()
++ */
++
++ /*!
++ \fn template <class X, class T> QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &other)
++ \relates QSharedPointer
++ \relates QWeakPointer
++
++ Returns a shared pointer to the pointer held by \a other, cast to
++ type \tt X. The types \tt T and \tt X must belong to one
++ hierarchy for the \tt static_cast to succeed.
++
++ The \a other object is converted first to a strong reference. If
++ that conversion fails (because the object it's pointing to has
++ already been deleted), this function returns a null
++ QSharedPointer.
++
++ Note that \tt X must have the same cv-qualifiers (\tt const and
++ \tt volatile) that \tt T has, or the code will fail to
++ compile. Use qSharedPointerConstCast to cast away the constness.
++
++ \sa QWeakPointer::toStrongRef(), qSharedPointerDynamicCast(), qSharedPointerConstCast()
++ */
++
++ /*!
++ \fn template <class X, class T> QSharedPointer<X> qSharedPointerStaticCast(const QSharedPointer<T> &other)
++ \since 6.12
++ \relates QSharedPointer
++
++ Returns a shared pointer to the pointer held by \a other, cast to
++ type \tt X. The types \tt T and \tt X must belong to one
++ hierarchy for the \tt static_cast to succeed.
++
++ Note that \tt X must have the same cv-qualifiers (\tt const and
++ \tt volatile) that \tt T has, or the code will fail to
++ compile. Use qSharedPointerConstCast to cast away the constness.
++
++ \sa QSharedPointer::staticCast(), qSharedPointerDynamicCast(), qSharedPointerConstCast()
++ */
++
++ /*!
++ \fn template <class X, class T> QSharedPointer<X> qSharedPointerStaticCast(QSharedPointer<T> &&other)
++ \relates QSharedPointer
++ \since 6.12
++ \overload qSharedPointerStaticCast(const QSharedPointer<T> &other)
++
++ \include qsharedpointer.cpp {cast-overload-for-arg} {other}
++
++ \sa QSharedPointer::staticCast(), qSharedPointerDynamicCast(), qSharedPointerConstCast()
++ */
++
++ /*!
++ \fn template <class X, class T> QSharedPointer<X> qSharedPointerStaticCast(const QWeakPointer<T> &other)
++ \since 6.12
++ \relates QSharedPointer
++ \relates QWeakPointer
++
++ Returns a shared pointer to the pointer held by \a other, cast to
++ type \tt X. The types \tt T and \tt X must belong to one
++ hierarchy for the \tt static_cast to succeed.
++
++ The \a other object is converted first to a strong reference. If
++ that conversion fails (because the object it's pointing to has
++ already been deleted), this function returns a null
++ QSharedPointer.
++
++ Note that \tt X must have the same cv-qualifiers (\tt const and
++ \tt volatile) that \tt T has, or the code will fail to
++ compile. Use qSharedPointerConstCast to cast away the constness.
++
++ \sa QWeakPointer::toStrongRef(), qSharedPointerDynamicCast(), qSharedPointerConstCast()
++ */
++
++ /*!
++ \fn template <class X, class T> QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src)
++ \relates QSharedPointer
++
++ Returns a shared pointer to the pointer held by \a src, using a
++ dynamic cast to type \tt X to obtain an internal pointer of the
++ appropriate type. If the \tt dynamic_cast fails, the object
++ returned will be null.
++
++ Note that \tt X must have the same cv-qualifiers (\tt const and
++ \tt volatile) that \tt T has, or the code will fail to
++ compile. Use qSharedPointerConstCast to cast away the constness.
++
++ \sa QSharedPointer::dynamicCast(), qSharedPointerStaticCast(), qSharedPointerConstCast()
++ */
++
++ /*!
++ \fn template <class X, class T> QSharedPointer<X> qSharedPointerDynamicCast(QSharedPointer<T> &&src)
++ \relates QSharedPointer
++ \since 6.9
++ \overload qSharedPointerDynamicCast(const QSharedPointer<T> &src)
++
++ \include qsharedpointer.cpp {cast-overload-for-arg} {src}
++
++ \sa QSharedPointer::dynamicCast(), qSharedPointerStaticCast(), qSharedPointerConstCast()
++ */
++
++ /*!
++ \fn template <class X, class T> QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src)
++ \relates QSharedPointer
++ \relates QWeakPointer
++
++ Returns a shared pointer to the pointer held by \a src, using a
++ dynamic cast to type \tt X to obtain an internal pointer of the
++ appropriate type. If the \tt dynamic_cast fails, the object
++ returned will be null.
++
++ The \a src object is converted first to a strong reference. If
++ that conversion fails (because the object it's pointing to has
++ already been deleted), this function also returns a null
++ QSharedPointer.
++
++ Note that \tt X must have the same cv-qualifiers (\tt const and
++ \tt volatile) that \tt T has, or the code will fail to
++ compile. Use qSharedPointerConstCast to cast away the constness.
++
++ \sa QWeakPointer::toStrongRef(), qSharedPointerStaticCast(), qSharedPointerConstCast()
++ */
++
++ /*!
++ \fn template <class X, class T> QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src)
++ \relates QSharedPointer
++
++ Returns a shared pointer to the pointer held by \a src, cast to
++ type \tt X. The types \tt T and \tt X must belong to one
++ hierarchy for the \tt const_cast to succeed. The \tt const and \tt
++ volatile differences between \tt T and \tt X are ignored.
++
++ \sa QSharedPointer::constCast(), qSharedPointerStaticCast(), qSharedPointerDynamicCast()
++ */
++
++ /*!
++ \fn template <class X, class T> QSharedPointer<X> qSharedPointerConstCast(QSharedPointer<T> &&src)
++ \relates QSharedPointer
++ \since 6.9
++ \overload qSharedPointerConstCast(const QSharedPointer<T> &src)
++
++ \include qsharedpointer.cpp {cast-overload-for-arg} {src}
++
++ \sa QSharedPointer::constCast(), qSharedPointerStaticCast(), qSharedPointerDynamicCast()
++ */
++
++ /*!
++ \fn template <class X, class T> QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src)
++ \relates QSharedPointer
++ \relates QWeakPointer
++
++ Returns a shared pointer to the pointer held by \a src, cast to
++ type \tt X. The types \tt T and \tt X must belong to one
++ hierarchy for the \tt const_cast to succeed. The \tt const and
++ \tt volatile differences between \tt T and \tt X are ignored.
++
++ The \a src object is converted first to a strong reference. If
++ that conversion fails (because the object it's pointing to has
++ already been deleted), this function returns a null
++ QSharedPointer.
++
++ \sa QWeakPointer::toStrongRef(), qSharedPointerStaticCast(), qSharedPointerDynamicCast()
++ */
++
++ /*!
++ \fn template <class X, class T> QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src)
++ \relates QSharedPointer
++ \since 4.6
++
++ \brief The qSharedPointerObjectCast function is for casting a shared pointer.
++
++ Returns a shared pointer to the pointer held by \a src, using a
++ \l qobject_cast() to type \tt X to obtain an internal pointer of the
++ appropriate type. If the \tt qobject_cast fails, the object
++ returned will be null.
++
++ Note that \tt X must have the same cv-qualifiers (\tt const and
++ \tt volatile) that \tt T has, or the code will fail to
++ compile. Use qSharedPointerConstCast to cast away the constness.
++
++ \sa QSharedPointer::objectCast(), qSharedPointerStaticCast(), qSharedPointerConstCast()
++ */
++
++ /*!
++ \fn template <class X, class T> QSharedPointer<X> qSharedPointerObjectCast(QSharedPointer<T> &&src)
++ \relates QSharedPointer
++ \since 6.9
++ \overload qSharedPointerObjectCast(const QSharedPointer<T> &src)
++
++ \include qsharedpointer.cpp {cast-overload-for-arg} {src}
++
++ \sa QSharedPointer::objectCast(), qSharedPointerStaticCast(), qSharedPointerConstCast()
++ */
++
++ /*!
++ \fn template <class X, class T> std::shared_ptr<X> qSharedPointerObjectCast(const std::shared_ptr<T> &src)
++ \relates QSharedPointer
++ \since 5.14
++
++ Returns a shared pointer to the pointer held by \a src, using a
++ \l qobject_cast() to type \tt X to obtain an internal pointer of the
++ appropriate type. If the \tt qobject_cast fails, the object
++ returned will be null.
++
++ Note that \tt X must have the same cv-qualifiers (\tt const and
++ \tt volatile) that \tt T has, or the code will fail to
++ compile. Use const_pointer_cast to cast away the constness.
++ */
++
++ /*!
++ \fn template <class X, class T> std::shared_ptr<X> qobject_pointer_cast(const std::shared_ptr<T> &src)
++ \relates QSharedPointer
++ \since 5.14
++
++ Returns a shared pointer to the pointer held by \a src.
++
++ Same as qSharedPointerObjectCast(). This function is provided for STL
++ compatibility.
++ */
++
++ /*!
++ \fn template <class X, class T> std::shared_ptr<X> qSharedPointerObjectCast(std::shared_ptr<T> &&src)
++ \relates QSharedPointer
++ \since 5.14
++
++ Returns a shared pointer to the pointer held by \a src, using a
++ \l qobject_cast() to type \tt X to obtain an internal pointer of the
++ appropriate type.
++
++ If the \tt qobject_cast succeeds, the function will return a valid shared
++ pointer, and \a src is reset to null. If the \tt qobject_cast fails, the
++ object returned will be null, and \a src will not be modified.
++
++ Note that \tt X must have the same cv-qualifiers (\tt const and
++ \tt volatile) that \tt T has, or the code will fail to
++ compile. Use const_pointer_cast to cast away the constness.
++ */
++
++ /*!
++ \fn template <class X, class T> std::shared_ptr<X> qobject_pointer_cast(std::shared_ptr<T> &&src)
++ \relates QSharedPointer
++ \since 5.14
++
++ Same as qSharedPointerObjectCast(). This function is provided for STL
++ compatibility.
++ */
++
++ /*!
++ \fn template <class X, class T> QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src)
++ \relates QSharedPointer
++ \relates QWeakPointer
++ \since 4.6
++
++ \brief The qSharedPointerObjectCast function is for casting a shared pointer.
++
++ Returns a shared pointer to the pointer held by \a src, using a
++ \l qobject_cast() to type \tt X to obtain an internal pointer of the
++ appropriate type. If the \tt qobject_cast fails, the object
++ returned will be null.
++
++ The \a src object is converted first to a strong reference. If
++ that conversion fails (because the object it's pointing to has
++ already been deleted), this function also returns a null
++ QSharedPointer.
++
++ Note that \tt X must have the same cv-qualifiers (\tt const and
++ \tt volatile) that \tt T has, or the code will fail to
++ compile. Use qSharedPointerConstCast to cast away the constness.
++
++ \sa QWeakPointer::toStrongRef(), qSharedPointerStaticCast(), qSharedPointerConstCast()
++ */
++
++
++ /*!
++ \fn template <class X, class T> QWeakPointer<X> qWeakPointerCast(const QWeakPointer<T> &src)
++ \relates QWeakPointer
++
++ Returns a weak pointer to the pointer held by \a src, cast to
++ type \tt X. The types \tt T and \tt X must belong to one
++ hierarchy for the \tt static_cast to succeed.
++
++ Note that \tt X must have the same cv-qualifiers (\tt const and
++ \tt volatile) that \tt T has, or the code will fail to
++ compile. Use qSharedPointerConstCast to cast away the constness.
++ */
++
++ #include <qset.h>
++ #include <qmutex.h>
++
++ #if !defined(QT_NO_QOBJECT)
++ #include "private/qobject_p.h"
++
++ QT_BEGIN_NAMESPACE
++
++ QT6_ONLY(
++ /*!
++ \internal
++ This function is called for a just-created QObject \a obj, to enable
++ the use of QSharedPointer and QWeakPointer in the future.
++ */
++ void QtSharedPointer::ExternalRefCountData::setQObjectShared(const QObject *, bool)
++ {}
++ )
++
++ QT6_ONLY(
++ /*!
++ \internal
++ This function is called when a QSharedPointer is created from a QWeakPointer
++
++ We check that the QWeakPointer was really created from a QSharedPointer, and
++ not from a QObject.
++ */
++ void QtSharedPointer::ExternalRefCountData::checkQObjectShared(const QObject *)
++ {
++ if (strongref.loadRelaxed() < 0)
++ qWarning("QSharedPointer: cannot create a QSharedPointer from a QObject-tracking QWeakPointer");
++ }
++ )
++
++ QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::getAndRef(const QObject *obj)
++ {
++ Q_ASSERT(obj);
++ QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject *>(obj));
++ Q_ASSERT_X(!d->wasDeleted, "QWeakPointer", "Detected QWeakPointer creation in a QObject being deleted");
++
++ ExternalRefCountData *that = d->sharedRefcount.loadAcquire();
++ if (that) {
++ that->weakref.ref();
++ return that;
++ }
++
++ // we can create the refcount data because it doesn't exist
++ ExternalRefCountData *x = ::new ExternalRefCountData(Qt::Uninitialized);
++ x->strongref.storeRelaxed(-1);
++ x->weakref.storeRelaxed(2); // the QWeakPointer that called us plus the QObject itself
++ x->destroyer = nullptr;
++
++ ExternalRefCountData *ret;
++ if (d->sharedRefcount.testAndSetOrdered(nullptr, x, ret)) { // ought to be release+acquire; this is acq_rel+acquire
++ ret = x;
++ } else {
++ // ~ExternalRefCountData has a Q_ASSERT, so we use this trick to
++ // only execute this if Q_ASSERTs are enabled
++ Q_ASSERT((x->weakref.storeRelaxed(0), true));
++ ::delete x;
++ ret->weakref.ref();
++ }
++ return ret;
++ }
++
++ /**
++ \internal
++ Returns a QSharedPointer<QObject> if the variant contains
++ a QSharedPointer<T> where T inherits QObject. Otherwise the behaviour is undefined.
++ */
++ QSharedPointer<QObject> QtSharedPointer::sharedPointerFromVariant_internal(const QVariant &variant)
++ {
++ Q_ASSERT(variant.metaType().flags() & QMetaType::SharedPointerToQObject);
++ return *reinterpret_cast<const QSharedPointer<QObject>*>(variant.constData());
++ }
++
++ /**
++ \internal
++ Returns a QWeakPointer<QObject> if the variant contains
++ a QWeakPointer<T> where T inherits QObject. Otherwise the behaviour is undefined.
++ */
++ QWeakPointer<QObject> QtSharedPointer::weakPointerFromVariant_internal(const QVariant &variant)
++ {
++ Q_ASSERT(variant.metaType().flags() & QMetaType::WeakPointerToQObject ||
++ variant.metaType().flags() & QMetaType::TrackingPointerToQObject);
++ return *reinterpret_cast<const QWeakPointer<QObject>*>(variant.constData());
++ }
++
++ QT_END_NAMESPACE
++
++ #endif
++
++
++
++ //# define QT_SHARED_POINTER_BACKTRACE_SUPPORT
++ # ifdef QT_SHARED_POINTER_BACKTRACE_SUPPORT
++ # if defined(__GLIBC__) && (__GLIBC__ >= 2) && !defined(__UCLIBC__) && !defined(QT_LINUXBASE)
++ # define BACKTRACE_SUPPORTED
++ # elif defined(Q_OS_DARWIN)
++ # define BACKTRACE_SUPPORTED
++ # endif
++ # endif
++
++ # if defined(BACKTRACE_SUPPORTED)
++ # include <sys/types.h>
++ # include <execinfo.h>
++ # include <stdio.h>
++ # include <unistd.h>
++ # include <sys/wait.h>
++
++ QT_BEGIN_NAMESPACE
++
++ static inline QByteArray saveBacktrace() __attribute__((always_inline));
++ static inline QByteArray saveBacktrace()
++ {
++ static const int maxFrames = 32;
++
++ QByteArray stacktrace;
++ stacktrace.resize(sizeof(void*) * maxFrames);
++ int stack_size = backtrace((void**)stacktrace.data(), maxFrames);
++ stacktrace.resize(sizeof(void*) * stack_size);
++
++ return stacktrace;
++ }
++
++ static void printBacktrace(QByteArray stacktrace)
++ {
++ void *const *stack = (void *const *)stacktrace.constData();
++ int stack_size = stacktrace.size() / sizeof(void*);
++ char **stack_symbols = backtrace_symbols(stack, stack_size);
++
++ int filter[2];
++ pid_t child = -1;
++ if (pipe(filter) != -1)
++ child = fork();
++ if (child == 0) {
++ // child process
++ dup2(fileno(stderr), fileno(stdout));
++ dup2(filter[0], fileno(stdin));
++ close(filter[0]);
++ close(filter[1]);
++ execlp("c++filt", "c++filt", "-n", NULL);
++
++ // execlp failed
++ execl("/bin/cat", "/bin/cat", NULL);
++ _exit(127);
++ }
++
++ // parent process
++ close(filter[0]);
++ FILE *output;
++ if (child == -1) {
++ // failed forking
++ close(filter[1]);
++ output = stderr;
++ } else {
++ output = fdopen(filter[1], "w");
++ }
++
++ fprintf(stderr, "Backtrace of the first creation (most recent frame first):\n");
++ for (int i = 0; i < stack_size; ++i) {
++ if (strlen(stack_symbols[i]))
++ fprintf(output, "#%-2d %s\n", i, stack_symbols[i]);
++ else
++ fprintf(output, "#%-2d %p\n", i, stack[i]);
++ }
++
++ if (child != -1) {
++ fclose(output);
++ waitpid(child, 0, 0);
++ }
++ }
++
++ QT_END_NAMESPACE
++
++ # endif // BACKTRACE_SUPPORTED
++
++ namespace {
++ QT_USE_NAMESPACE
++ struct Data {
++ const volatile void *pointer;
++ # ifdef BACKTRACE_SUPPORTED
++ QByteArray backtrace;
++ # endif
++ };
++
++ class KnownPointers
++ {
++ public:
++ QMutex mutex;
++ QHash<const void *, Data> dPointers;
++ QHash<const volatile void *, const void *> dataPointers;
++ };
++ }
++
++ Q_GLOBAL_STATIC(KnownPointers, knownPointers)
++
++ QT_BEGIN_NAMESPACE
++
++ namespace QtSharedPointer {
++ Q_AUTOTEST_EXPORT void internalSafetyCheckCleanCheck();
++ }
++
++ /*!
++ \internal
++ */
++ void QtSharedPointer::internalSafetyCheckAdd(const void *d_ptr, const volatile void *ptr)
++ {
++ KnownPointers *const kp = knownPointers();
++ if (!kp)
++ return; // end-game: the application is being destroyed already
++
++ if (!ptr) {
++ // nullptr is allowed to be tracked by more than one QSharedPointer, so we
++ // need something else to put in our tracking structures
++ ptr = d_ptr;
++ }
++
++ QMutexLocker lock(&kp->mutex);
++ Q_ASSERT(!kp->dPointers.contains(d_ptr));
++
++ //qDebug("Adding d=%p value=%p", d_ptr, ptr);
++
++ const void *other_d_ptr = kp->dataPointers.value(ptr, nullptr);
++ if (Q_UNLIKELY(other_d_ptr)) {
++ # ifdef BACKTRACE_SUPPORTED
++ printBacktrace(knownPointers()->dPointers.value(other_d_ptr).backtrace);
++ # endif
++ qFatal("QSharedPointer: internal self-check failed: pointer %p was already tracked "
++ "by another QSharedPointer object %p", ptr, other_d_ptr);
++ }
++
++ Data data;
++ data.pointer = ptr;
++ # ifdef BACKTRACE_SUPPORTED
++ data.backtrace = saveBacktrace();
++ # endif
++
++ kp->dPointers.insert(d_ptr, data);
++ kp->dataPointers.insert(ptr, d_ptr);
++ Q_ASSERT(kp->dPointers.size() == kp->dataPointers.size());
++ }
++
++ /*!
++ \internal
++ */
++ void QtSharedPointer::internalSafetyCheckRemove(const void *d_ptr)
++ {
++ KnownPointers *const kp = knownPointers();
++ if (!kp)
++ return; // end-game: the application is being destroyed already
++
++ QMutexLocker lock(&kp->mutex);
++
++ const auto it = kp->dPointers.constFind(d_ptr);
++ if (Q_UNLIKELY(it == kp->dPointers.cend())) {
++ qFatal("QSharedPointer: internal self-check inconsistency: pointer %p was not tracked. "
++ "To use QT_SHAREDPOINTER_TRACK_POINTERS, you have to enable it throughout "
++ "in your code.", d_ptr);
++ }
++
++ const auto it2 = kp->dataPointers.constFind(it->pointer);
++ Q_ASSERT(it2 != kp->dataPointers.cend());
++
++ //qDebug("Removing d=%p value=%p", d_ptr, it->pointer);
++
++ // remove entries
++ kp->dataPointers.erase(it2);
++ kp->dPointers.erase(it);
++ Q_ASSERT(kp->dPointers.size() == kp->dataPointers.size());
++ }
++
++ /*!
++ \internal
++ Called by the QSharedPointer autotest
++ */
++ void QtSharedPointer::internalSafetyCheckCleanCheck()
++ {
++ # ifdef QT_BUILD_INTERNAL
++ KnownPointers *const kp = knownPointers();
++ Q_ASSERT_X(kp, "internalSafetyCheckSelfCheck()", "Called after global statics deletion!");
++
++ if (Q_UNLIKELY(kp->dPointers.size() != kp->dataPointers.size()))
++ qFatal("Internal consistency error: the number of pointers is not equal!");
++
++ if (Q_UNLIKELY(!kp->dPointers.isEmpty()))
++ qFatal("Pointer cleaning failed: %d entries remaining", int(kp->dPointers.size()));
++ # endif
++ }
++
++ QT_END_NAMESPACE