Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qsharedpointer_impl.h
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// Copyright (C) 2022 Intel Corporation.
3// Copyright (C) 2019 Klarälvdalens Datakonsult AB.
4// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
5// Qt-Security score:significant reason:default
6
7#ifndef Q_QDOC
8
9#ifndef QSHAREDPOINTER_H
10#error Do not include qsharedpointer_impl.h directly
11#endif
12
13#if 0
14#pragma qt_sync_skip_header_check
15#pragma qt_sync_stop_processing
16#endif
17
18#if 0
19// These macros are duplicated here to make syncqt not complain a about
20// this header, as we have a "qt_sync_stop_processing" below, which in turn
21// is here because this file contains a template mess and duplicates the
22// classes found in qsharedpointer.h
23QT_BEGIN_NAMESPACE
24QT_END_NAMESPACE
25#pragma qt_sync_stop_processing
26#endif
27
28#include <new>
29#include <QtCore/qatomic.h>
30#include <QtCore/qhashfunctions.h>
31#include <QtCore/qmetatype.h> // for IsPointerToTypeDerivedFromQObject
32#include <QtCore/qxptype_traits.h>
33
34#include <memory>
35
36QT_BEGIN_NAMESPACE
37
38class QObject;
39template <class T>
40T qobject_cast(const QObject *object);
41
42//
43// forward declarations
44//
45template <class T> class QWeakPointer;
46template <class T> class QSharedPointer;
47template <class T> class QEnableSharedFromThis;
48
49class QVariant;
50
51template <class X, class T>
53template <class X, class T>
55template <class X, class T>
57template <class X, class T>
59template <class X, class T>
61template <class X, class T>
63template <class X, class T>
65template <class X, class T>
67
68#ifndef QT_NO_QOBJECT
69template <class X, class T>
71template <class X, class T>
73#endif
74
75namespace QtPrivate {
77}
78
79namespace QtSharedPointer {
80 template <class T> class ExternalRefCount;
81
82 template <class X, class Y> QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
83 template <class X, class Y> QSharedPointer<X> movePointer(X * ptr, QSharedPointer<Y> &&src);
84
85 // used in debug mode to verify the reuse of pointers
86 Q_CORE_EXPORT void internalSafetyCheckAdd(const void *, const volatile void *);
88
89 template <class T, typename Klass, typename RetVal>
90 inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)())
91 { if (t) (t->*memberDeleter)(); }
92 template <class T, typename Deleter>
93 inline void executeDeleter(T *t, Deleter d)
94 { d(t); }
95 struct NormalDeleter {};
96
97 // this uses partial template specialization
98 template <class T> struct RemovePointer;
99 template <class T> struct RemovePointer<T *> { typedef T Type; };
100 template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; };
101 template <class T> struct RemovePointer<QWeakPointer<T> > { typedef T Type; };
102
103 // This class is the d-pointer of QSharedPointer and QWeakPointer.
104 //
105 // It is a reference-counted reference counter. "strongref" is the inner
106 // reference counter, and it tracks the lifetime of the pointer itself.
107 // "weakref" is the outer reference counter and it tracks the lifetime of
108 // the ExternalRefCountData object.
109 //
110 // The deleter is stored in the destroyer member and is always a pointer to
111 // a static function in ExternalRefCountWithCustomDeleter or in
112 // ExternalRefCountWithContiguousData
114 {
119
121 : destroyer(d)
122 {
123 strongref.storeRelaxed(1);
124 weakref.storeRelaxed(1);
125 }
127 ~ExternalRefCountData() { Q_ASSERT(!weakref.loadRelaxed()); Q_ASSERT(strongref.loadRelaxed() <= 0); }
128
129 void destroy() { destroyer(this); }
130
131#ifndef QT_NO_QOBJECT
132 Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *);
134 Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable);
135 )
137#endif
138 inline void checkQObjectShared(...) { }
139 inline void setQObjectShared(...) { }
140
141 // Normally, only subclasses of ExternalRefCountData are allocated
142 // One exception exists in getAndRef; that uses the global operator new
143 // to prevent a mismatch with the custom operator delete
144 inline void *operator new(std::size_t) = delete;
145 // placement new
146 inline void *operator new(std::size_t, void *ptr) noexcept { return ptr; }
147 inline void operator delete(void *ptr) { ::operator delete(ptr); }
148 inline void operator delete(void *, void *) { }
149 };
150 // sizeof(ExternalRefCountData) = 12 (32-bit) / 16 (64-bit)
151
152 template <class T, typename Deleter>
154 {
155 Deleter deleter;
156 T *ptr;
157
158 CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {}
159 void execute() { executeDeleter(ptr, deleter); }
160 };
161 // sizeof(CustomDeleter) = sizeof(Deleter) + sizeof(void*) + padding
162 // for Deleter = stateless functor: 8 (32-bit) / 16 (64-bit) due to padding
163 // for Deleter = function pointer: 8 (32-bit) / 16 (64-bit)
164 // for Deleter = PMF: 12 (32-bit) / 24 (64-bit) (GCC)
165
166 // This specialization of CustomDeleter for a deleter of type NormalDeleter
167 // is an optimization: instead of storing a pointer to a function that does
168 // the deleting, we simply delete the pointer ourselves.
169 template <class T>
171 {
172 T *ptr;
173
175 void execute() { delete ptr; }
176 };
177 // sizeof(CustomDeleter specialization) = sizeof(void*)
178
179 // This class extends ExternalRefCountData and implements
180 // the static function that deletes the object. The pointer and the
181 // custom deleter are kept in the "extra" member so we can construct
182 // and destruct it independently of the full structure.
183 template <class T, typename Deleter>
185 {
188 CustomDeleter<T, Deleter> extra;
189
190 static inline void deleter(ExternalRefCountData *self)
191 {
192 Self *realself = static_cast<Self *>(self);
193 realself->extra.execute();
194
195 // delete the deleter too
196 realself->extra.~CustomDeleter<T, Deleter>();
197 }
199 {
201 deleter(self);
202 }
203
204 static inline Self *create(T *ptr, Deleter userDeleter, DestroyerFn actualDeleter)
205 {
206 Self *d = static_cast<Self *>(::operator new(sizeof(Self)));
207
208 // initialize the two sub-objects
209 new (&d->extra) CustomDeleter<T, Deleter>(ptr, userDeleter);
210 new (d) BaseClass(actualDeleter); // can't throw
211
212 return d;
213 }
214 private:
215 // prevent construction
216 ExternalRefCountWithCustomDeleter() = delete;
217 ~ExternalRefCountWithCustomDeleter() = delete;
219 };
220
221 // This class extends ExternalRefCountData and adds a "T"
222 // member. That way, when the create() function is called, we allocate
223 // memory for both QSharedPointer's d-pointer and the actual object being
224 // tracked.
225 template <class T>
227 {
229 typedef typename std::remove_cv<T>::type NoCVType;
231
232 static void deleter(ExternalRefCountData *self)
233 {
235 static_cast<ExternalRefCountWithContiguousData *>(self);
236 that->data.~T();
237 Q_UNUSED(that); // MSVC warns if T has a trivial destructor
238 }
240 {
242 deleter(self);
243 }
245
246 static inline ExternalRefCountData *create(NoCVType **ptr, DestroyerFn destroy)
247 {
249 static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData)));
250
251 // initialize the d-pointer sub-object
252 // leave d->data uninitialized
253 new (d) Parent(destroy); // can't throw
254
255 *ptr = &d->data;
256 return d;
257 }
258
259 private:
260 // prevent construction
261 ExternalRefCountWithContiguousData() = delete;
262 ~ExternalRefCountWithContiguousData() = delete;
264 };
265
266#ifndef QT_NO_QOBJECT
269#endif
270} // namespace QtSharedPointer
271
272template <class T> class QSharedPointer
273{
275 template <typename X>
276 using IfCompatible = typename std::enable_if<std::is_convertible<X*, T*>::value, bool>::type;
277
278public:
279 typedef T Type;
280 typedef T element_type;
281 typedef T value_type;
283 typedef const value_type *const_pointer;
287
288 T *data() const noexcept { return value.get(); }
289 T *get() const noexcept { return value.get(); }
290 bool isNull() const noexcept { return !data(); }
291 explicit operator bool() const noexcept { return !isNull(); }
292 bool operator !() const noexcept { return isNull(); }
293 T &operator*() const { return *data(); }
294 T *operator->() const noexcept { return data(); }
295
297 constexpr QSharedPointer() noexcept : value(nullptr), d(nullptr) { }
298 ~QSharedPointer() { deref(); }
299
301 constexpr QSharedPointer(std::nullptr_t) noexcept : value(nullptr), d(nullptr) { }
302
303 template <class X, IfCompatible<X> = true>
305 inline explicit QSharedPointer(X *ptr) : value(ptr) // noexcept
307
308 template <class X, typename Deleter, IfCompatible<X> = true>
312
313 template <typename Deleter>
316 { internalConstruct(static_cast<T *>(nullptr), deleter); }
317
320 { if (d) ref(); }
321 QSharedPointer &operator=(const QSharedPointer &other) noexcept
322 {
323 QSharedPointer copy(other);
324 swap(copy);
325 return *this;
326 }
329 : value(other.value.get()), d(other.d)
330 {
331 other.d = nullptr;
332 other.value = nullptr;
333 }
335
336 template <class X, IfCompatible<X> = true>
339 : value(other.value.get()), d(other.d)
340 {
341 other.d = nullptr;
342 other.value = nullptr;
343 }
344
345 template <class X, IfCompatible<X> = true>
347 {
349 swap(moved);
350 return *this;
351 }
352
353 template <class X, IfCompatible<X> = true>
356 { if (d) ref(); }
357
358 template <class X, IfCompatible<X> = true>
360 {
362 swap(copy);
363 return *this;
364 }
365
366 template <class X, IfCompatible<X> = true>
368 inline QSharedPointer(const QWeakPointer<X> &other) : value(nullptr), d(nullptr)
369 { *this = other; }
370
371 template <class X, IfCompatible<X> = true>
373 { internalSet(other.d, other.value); return *this; }
374
375 inline void swap(QSharedPointer &other) noexcept
376 { this->internalSwap(other); }
377
378 inline void reset() { clear(); }
379 inline void reset(T *t)
381 template <typename Deleter>
382 inline void reset(T *t, Deleter deleter)
384
385 template <class X>
387 {
388 return qSharedPointerStaticCast<X>(*this);
389 }
390
391 template <class X>
393 {
394 return qSharedPointerStaticCast<X>(std::move(*this));
395 }
396
397 template <class X>
399 {
400 return qSharedPointerDynamicCast<X>(*this);
401 }
402
403 template <class X>
405 {
406 return qSharedPointerDynamicCast<X>(std::move(*this));
407 }
408
409 template <class X>
411 {
412 return qSharedPointerConstCast<X>(*this);
413 }
414
415 template <class X>
417 {
418 return qSharedPointerConstCast<X>(std::move(*this));
419 }
420
421#ifndef QT_NO_QOBJECT
422 template <class X>
424 {
425 return qSharedPointerObjectCast<X>(*this);
426 }
427
428 template <class X>
430 {
431 return qSharedPointerObjectCast<X>(std::move(*this));
432 }
433#endif
434
435 inline void clear() { QSharedPointer copy; swap(copy); }
436
438
439 template <typename... Args>
440 [[nodiscard]] static QSharedPointer create(Args && ...arguments)
441 {
443# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
444 typename Private::DestroyerFn destroy = &Private::safetyCheckDeleter;
445# else
446 typename Private::DestroyerFn destroy = &Private::deleter;
447# endif
448 typename Private::DestroyerFn noDestroy = &Private::noDeleter;
449 QSharedPointer result(Qt::Uninitialized);
450 typename std::remove_cv<T>::type *ptr;
451 result.d = Private::create(&ptr, noDestroy);
452
453 // now initialize the data
454 new (ptr) T(std::forward<Args>(arguments)...);
455 result.value.reset(ptr);
456 result.d->destroyer = destroy;
457 result.d->setQObjectShared(result.value.get(), true);
458# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
459 internalSafetyCheckAdd(result.d, result.value.get());
460# endif
461 result.enableSharedFromThis(result.data());
462 return result;
463 }
464
465 template <typename X>
466 bool owner_before(const QSharedPointer<X> &other) const noexcept
467 { return std::less<>()(d, other.d); }
468 template <typename X>
469 bool owner_before(const QWeakPointer<X> &other) const noexcept
470 { return std::less<>()(d, other.d); }
471
472 template <typename X>
473 bool owner_equal(const QSharedPointer<X> &other) const noexcept
474 { return d == other.d; }
475 template <typename X>
476 bool owner_equal(const QWeakPointer<X> &other) const noexcept
477 { return d == other.d; }
478
479 size_t owner_hash() const noexcept
480 { return std::hash<Data *>()(d); }
481
482private:
483 template <typename X>
484 friend bool comparesEqual(const QSharedPointer &lhs, const QSharedPointer<X> &rhs) noexcept
485 { return lhs.data() == rhs.data(); }
486 template <typename X>
487 friend Qt::strong_ordering
488 compareThreeWay(const QSharedPointer &lhs, const QSharedPointer<X> &rhs) noexcept
489 {
490 return Qt::compareThreeWay(lhs.value, rhs.data());
491 }
492 QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, QSharedPointer<T>, QSharedPointer<X>,
493 /* non-constexpr */, noexcept(true),
494 template <typename X>)
495
496 template <typename X>
497 friend bool comparesEqual(const QSharedPointer &lhs, X *rhs) noexcept
498 { return lhs.data() == rhs; }
499 template <typename X>
501 { return Qt::compareThreeWay(lhs.value, rhs); }
502 Q_DECLARE_STRONGLY_ORDERED(QSharedPointer, X*, template <typename X>)
503
504 friend bool comparesEqual(const QSharedPointer &lhs, std::nullptr_t) noexcept
505 { return lhs.data() == nullptr; }
506 friend Qt::strong_ordering
508 { return Qt::compareThreeWay(lhs.value, nullptr); }
510
512 explicit QSharedPointer(Qt::Initialization) {}
513
514 void deref() noexcept
515 { deref(d); }
516 static void deref(Data *dd) noexcept
517 {
518 if (!dd) return;
519 if (!dd->strongref.deref()) {
520 dd->destroy();
521 }
522 if (!dd->weakref.deref())
523 delete dd;
524 }
525
526 template <class X>
528 {
530 }
531
532 inline void enableSharedFromThis(...) {}
533
534 template <typename X, typename Deleter>
535 inline void internalConstruct(X *ptr, Deleter deleter)
536 {
538# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
540# else
542# endif
544
545#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
547#endif
549 }
550
551 void internalSwap(QSharedPointer &other) noexcept
552 {
555 }
556
557 template <class X> friend class QSharedPointer;
558 template <class X> friend class QWeakPointer;
559 template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
560 template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::movePointer(X * ptr, QSharedPointer<Y> &&src);
561 void ref() const noexcept { d->weakref.ref(); d->strongref.ref(); }
562
563 inline void internalSet(Data *o, T *actual)
564 {
565 if (o) {
566 // increase the strongref, but never up from zero
567 // or less (-1 is used by QWeakPointer on untracked QObject)
568 int tmp = o->strongref.loadRelaxed();
569 while (tmp > 0) {
570 // try to increment from "tmp" to "tmp + 1"
571 if (o->strongref.testAndSetRelaxed(tmp, tmp + 1))
572 break; // succeeded
573 tmp = o->strongref.loadRelaxed(); // failed, try again
574 }
575
576 if (tmp > 0)
577 o->weakref.ref();
578 else
579 o = nullptr;
580 }
581
582 qt_ptr_swap(d, o);
583 this->value.reset(actual);
584 if (!d || d->strongref.loadRelaxed() == 0)
585 this->value = nullptr;
586
587 // dereference saved data
588 deref(o);
589 }
590
591 Qt::totally_ordered_wrapper<Type *> value;
592 Data *d;
593};
594
595template <class T>
597{
599 template <typename X>
601 std::negation<std::is_same<T, X>>, // don't make accidental copy/move SMFs
602 std::is_convertible<X*, T*>
603 >, bool>;
604
605 template <typename X>
606 using IfVirtualBase = typename std::enable_if<qxp::is_virtual_base_of_v<T, X>, bool>::type;
607
608 template <typename X>
609 using IfNotVirtualBase = typename std::enable_if<!qxp::is_virtual_base_of_v<T, X>, bool>::type;
610
611public:
612 typedef T element_type;
613 typedef T value_type;
615 typedef const value_type *const_pointer;
619
620 bool isNull() const noexcept { return d == nullptr || d->strongref.loadRelaxed() == 0 || value == nullptr; }
621 explicit operator bool() const noexcept { return !isNull(); }
622 bool operator !() const noexcept { return isNull(); }
623
625 constexpr QWeakPointer() noexcept : d(nullptr), value(nullptr) { }
626 inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
627
630 { if (d) d->weakref.ref(); }
633 : d(other.d), value(other.value)
634 {
635 other.d = nullptr;
636 other.value = nullptr;
637 }
639
640 template <class X, IfCompatible<X> = true, IfNotVirtualBase<X> = true>
643 : d(std::exchange(other.d, nullptr)),
644 value(std::exchange(other.value, nullptr))
645 {
646 }
647
648 template <class X, IfCompatible<X> = true, IfVirtualBase<X> = true>
651 : d(other.d), value(other.toStrongRef().get()) // must go through QSharedPointer, see below
652 {
653 other.d = nullptr;
654 other.value = nullptr;
655 }
656
657 template <class X, IfCompatible<X> = true>
659 {
661 swap(moved);
662 return *this;
663 }
664
666 {
668 swap(copy);
669 return *this;
670 }
671
672 void swap(QWeakPointer &other) noexcept
673 {
674 qt_ptr_swap(this->d, other.d);
676 }
677
679 inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data())
680 { if (d) d->weakref.ref();}
682 {
683 internalSet(o.d, o.value.get());
684 return *this;
685 }
686
687 template <class X, IfCompatible<X> = true>
689 inline QWeakPointer(const QWeakPointer<X> &o) : d(nullptr), value(nullptr)
690 { *this = o; }
691
692 template <class X, IfCompatible<X> = true>
694 {
695 // conversion between X and T could require access to the virtual table
696 // so force the operation to go through QSharedPointer
697 *this = o.toStrongRef();
698 return *this;
699 }
700
701 template <class X, IfCompatible<X> = true>
703 inline QWeakPointer(const QSharedPointer<X> &o) : d(nullptr), value(nullptr)
704 { *this = o; }
705
706 template <class X, IfCompatible<X> = true>
708 {
709 internalSet(o.d, o.data());
710 return *this;
711 }
712
713 inline void clear() { *this = QWeakPointer(); }
714
715 [[nodiscard]] QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
716 // std::weak_ptr compatibility:
717 [[nodiscard]] QSharedPointer<T> lock() const { return toStrongRef(); }
718
719 template <class X>
720 bool operator==(const QWeakPointer<X> &o) const noexcept
721 { return d == o.d && value == static_cast<const T *>(o.value); }
722
723 template <class X>
724 bool operator!=(const QWeakPointer<X> &o) const noexcept
725 { return !(*this == o); }
726
727 template <class X>
728 bool operator==(const QSharedPointer<X> &o) const noexcept
729 { return d == o.d; }
730
731 template <class X>
732 bool operator!=(const QSharedPointer<X> &o) const noexcept
733 { return !(*this == o); }
734
735 template <typename X>
736 friend bool operator==(const QSharedPointer<X> &p1, const QWeakPointer &p2) noexcept
737 { return p2 == p1; }
738 template <typename X>
739 friend bool operator!=(const QSharedPointer<X> &p1, const QWeakPointer &p2) noexcept
740 { return p2 != p1; }
741
742 friend bool operator==(const QWeakPointer &p, std::nullptr_t)
743 { return p.isNull(); }
744 friend bool operator==(std::nullptr_t, const QWeakPointer &p)
745 { return p.isNull(); }
746 friend bool operator!=(const QWeakPointer &p, std::nullptr_t)
747 { return !p.isNull(); }
748 friend bool operator!=(std::nullptr_t, const QWeakPointer &p)
749 { return !p.isNull(); }
750
751 template <typename X>
752 bool owner_before(const QWeakPointer<X> &other) const noexcept
753 { return std::less<>()(d, other.d); }
754 template <typename X>
755 bool owner_before(const QSharedPointer<X> &other) const noexcept
756 { return std::less<>()(d, other.d); }
757
758 template <typename X>
759 bool owner_equal(const QWeakPointer<X> &other) const noexcept
760 { return d == other.d; }
761 template <typename X>
762 bool owner_equal(const QSharedPointer<X> &other) const noexcept
763 { return d == other.d; }
764
765 size_t owner_hash() const noexcept
766 { return std::hash<Data *>()(d); }
767
768private:
770 template <class X> friend class QSharedPointer;
771 template <class X> friend class QWeakPointer;
772 template <class X> friend class QPointer;
773
774 template <class X>
775 inline QWeakPointer &assign(X *ptr)
776 { return *this = QWeakPointer<T>(ptr, true); }
777
778#ifndef QT_NO_QOBJECT
780 QWeakPointer(T *ptr, bool)
781 : d{ptr ? Data::getAndRef(ptr) : nullptr}, value{ptr}
782 { }
783
784 template <class X, IfCompatible<X> = true>
786 inline QWeakPointer(X *ptr, bool) : d(ptr ? Data::getAndRef(ptr) : nullptr), value(ptr)
787 { }
788#endif
789
790 inline void internalSet(Data *o, T *actual)
791 {
792 if (d == o) return;
793 if (o)
794 o->weakref.ref();
795 if (d && !d->weakref.deref())
796 delete d;
797 d = o;
798 value = actual;
799 }
800
801 // ### TODO - QTBUG-88102: remove all users of this API; no one should ever
802 // access a weak pointer's data but the weak pointer itself
803 inline T *internalData() const noexcept
804 {
805 return d == nullptr || d->strongref.loadRelaxed() == 0 ? nullptr : value;
806 }
807
808 Data *d;
809 T *value;
810};
811
812namespace QtPrivate {
814 template <typename T>
815 static T *internalData(const QWeakPointer<T> &p) noexcept { return p.internalData(); }
816};
817// hack to delay name lookup to instantiation time by making
818// EnableInternalData a dependent name:
819template <typename T>
821}
822
823template <class T>
825{
826protected:
830
831public:
832 inline QSharedPointer<T> sharedFromThis() { return QSharedPointer<T>(weakPointer); }
833 inline QSharedPointer<const T> sharedFromThis() const { return QSharedPointer<const T>(weakPointer); }
834
835private:
836 template <class X> friend class QSharedPointer;
837 template <class X>
838 inline void initializeFromSharedPointer(const QSharedPointer<X> &ptr) const
839 {
840 weakPointer = ptr;
841 }
842
843 mutable QWeakPointer<T> weakPointer;
844};
845
846//
847// operator-
848//
849template <class T, class X>
851{
852 return ptr1.data() - ptr2.data();
853}
854template <class T, class X>
856{
857 return ptr1.data() - ptr2;
858}
859template <class T, class X>
861{
862 return ptr1 - ptr2.data();
863}
864
865//
866// qHash
867//
868template <class T>
869Q_INLINE_TEMPLATE size_t qHash(const QSharedPointer<T> &ptr, size_t seed = 0)
870{
871 return qHash(ptr.data(), seed);
872}
873
874
875template <class T>
876Q_INLINE_TEMPLATE QWeakPointer<T> QSharedPointer<T>::toWeakRef() const
877{
878 return QWeakPointer<T>(*this);
879}
880
881template <class T>
882inline void swap(QSharedPointer<T> &p1, QSharedPointer<T> &p2) noexcept
883{ p1.swap(p2); }
884
885template <class T>
886inline void swap(QWeakPointer<T> &p1, QWeakPointer<T> &p2) noexcept
887{ p1.swap(p2); }
888
889namespace QtSharedPointer {
890// helper functions:
891 template <class X, class T>
898
899 template <class X, class T>
901 {
903 result.d = std::exchange(src.d, nullptr);
905 src.value.reset(nullptr);
906 return result;
907 }
908}
909
910// cast operators
911template <class X, class T>
912Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &src)
913{
914 return qSharedPointerStaticCast<X>(src);
915}
916template <class X, class T>
917Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(QSharedPointer<T> &&src)
918{
919 return qSharedPointerStaticCast<X>(std::move(src));
920}
921template <class X, class T>
922Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &src)
923{
924 return qSharedPointerCast<X>(src.toStrongRef());
925}
926template <class X, class T>
927Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerStaticCast(const QSharedPointer<T> &src)
928{
929 X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
930 return QtSharedPointer::copyAndSetPointer(ptr, src);
931}
932template <class X, class T>
933Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerStaticCast(QSharedPointer<T> &&src)
934{
935 X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
936 return QtSharedPointer::movePointer(ptr, std::move(src));
937}
938template <class X, class T>
939Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerStaticCast(const QWeakPointer<T> &src)
940{
941 return qSharedPointerStaticCast<X>(src.toStrongRef());
942}
943
944template <class X, class T>
945Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src)
946{
947 X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
948 if (!ptr)
949 return QSharedPointer<X>();
950 return QtSharedPointer::copyAndSetPointer(ptr, src);
951}
952template <class X, class T>
953Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(QSharedPointer<T> &&src)
954{
955 X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
956 if (!ptr)
957 return QSharedPointer<X>();
958 return QtSharedPointer::movePointer(ptr, std::move(src));
959}
960template <class X, class T>
961Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src)
962{
963 return qSharedPointerDynamicCast<X>(src.toStrongRef());
964}
965
966template <class X, class T>
967Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src)
968{
969 X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
970 return QtSharedPointer::copyAndSetPointer(ptr, src);
971}
972template <class X, class T>
973Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(QSharedPointer<T> &&src)
974{
975 X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
976 return QtSharedPointer::movePointer(ptr, std::move(src));
977}
978template <class X, class T>
979Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src)
980{
981 return qSharedPointerConstCast<X>(src.toStrongRef());
982}
983
984template <class X, class T>
985Q_INLINE_TEMPLATE
986QWeakPointer<X> qWeakPointerCast(const QSharedPointer<T> &src)
987{
988 return qSharedPointerCast<X>(src).toWeakRef();
989}
990
991#ifndef QT_NO_QOBJECT
992template <class X, class T>
993Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src)
994{
995 X *ptr = qobject_cast<X *>(src.data());
996 if (!ptr)
997 return QSharedPointer<X>();
998 return QtSharedPointer::copyAndSetPointer(ptr, src);
999}
1000template <class X, class T>
1001Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(QSharedPointer<T> &&src)
1002{
1003 X *ptr = qobject_cast<X *>(src.data());
1004 if (!ptr)
1005 return QSharedPointer<X>();
1006 return QtSharedPointer::movePointer(ptr, std::move(src));
1007}
1008template <class X, class T>
1009Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src)
1010{
1011 return qSharedPointerObjectCast<X>(src.toStrongRef());
1012}
1013
1014template <class X, class T>
1017{
1018 return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type>(src);
1019}
1020template <class X, class T>
1023{
1024 return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type>(std::move(src));
1025}
1026template <class X, class T>
1029{
1030 return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type>(src);
1031}
1032
1033/// ### TODO - QTBUG-88102: make this use toStrongRef() (once support for
1034/// storing non-managed QObjects in QWeakPointer is removed)
1035template<typename T>
1036QWeakPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
1037qWeakPointerFromVariant(const QVariant &variant)
1038{
1039 return QWeakPointer<T>(qobject_cast<T*>(QtPrivate::EnableInternalData::internalData(QtSharedPointer::weakPointerFromVariant_internal(variant))));
1040}
1041template<typename T>
1042QSharedPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
1043qSharedPointerFromVariant(const QVariant &variant)
1044{
1045 return qSharedPointerObjectCast<T>(QtSharedPointer::sharedPointerFromVariant_internal(variant));
1046}
1047
1048// std::shared_ptr helpers
1049
1050template <typename X, class T>
1051std::shared_ptr<X> qobject_pointer_cast(const std::shared_ptr<T> &src)
1052{
1053 using element_type = typename std::shared_ptr<X>::element_type;
1054 if (auto ptr = qobject_cast<element_type *>(src.get()))
1055 return std::shared_ptr<X>(src, ptr);
1056 return std::shared_ptr<X>();
1057}
1058
1059template <typename X, class T>
1060std::shared_ptr<X> qobject_pointer_cast(std::shared_ptr<T> &&src)
1061{
1062 using element_type = typename std::shared_ptr<X>::element_type;
1063 auto castResult = qobject_cast<element_type *>(src.get());
1064 if (castResult) {
1065 // C++2a's move aliasing constructor will leave src empty.
1066 // Before C++2a we don't really know if the compiler has support for it.
1067 // The move aliasing constructor is the resolution for LWG2996,
1068 // which does not impose a feature-testing macro. So: clear src.
1069 return std::shared_ptr<X>(std::exchange(src, nullptr), castResult);
1070 }
1071 return std::shared_ptr<X>();
1072}
1073
1074template <typename X, class T>
1075std::shared_ptr<X> qSharedPointerObjectCast(const std::shared_ptr<T> &src)
1076{
1077 return qobject_pointer_cast<X>(src);
1078}
1079
1080template <typename X, class T>
1081std::shared_ptr<X> qSharedPointerObjectCast(std::shared_ptr<T> &&src)
1082{
1083 return qobject_pointer_cast<X>(std::move(src));
1084}
1085
1086#endif
1087
1090
1091
1092QT_END_NAMESPACE
1093
1094#endif
void operator delete(void *)
QSharedPointer< T > sharedFromThis()
QEnableSharedFromThis(const QEnableSharedFromThis &)
QEnableSharedFromThis & operator=(const QEnableSharedFromThis &)
QEnableSharedFromThis()=default
QSharedPointer< const T > sharedFromThis() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
\inmodule QtCore
friend bool comparesEqual(const QSharedPointer &lhs, const QSharedPointer< X > &rhs) noexcept
T * operator->() const noexcept
Provides access to the shared pointer's members.
T & operator*() const
Provides access to the shared pointer's members.
T * data() const noexcept
Returns the value of the pointer referenced by this object.
~QSharedPointer()
Destroys this QSharedPointer object.
bool owner_equal(const QSharedPointer< X > &other) const noexcept
operator bool() const noexcept
Returns true if the contained pointer is not \nullptr.
const value_type & const_reference
bool owner_before(const QSharedPointer< X > &other) const noexcept
friend QSharedPointer< X > QtSharedPointer::movePointer(X *ptr, QSharedPointer< Y > &&src)
friend Qt::strong_ordering compareThreeWay(const QSharedPointer &lhs, const QSharedPointer< X > &rhs) noexcept
const value_type * const_pointer
bool isNull() const noexcept
Returns true if this object refers to \nullptr.
bool operator!() const noexcept
Returns true if this object refers to \nullptr.
QSharedPointer & operator=(const QSharedPointer &other) noexcept
Makes this object share other's pointer.
bool owner_equal(const QWeakPointer< X > &other) const noexcept
static QSharedPointer create(Args &&...arguments)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool owner_before(const QWeakPointer< X > &other) const noexcept
size_t owner_hash() const noexcept
T * get() const noexcept
friend QSharedPointer< X > QtSharedPointer::copyAndSetPointer(X *ptr, const QSharedPointer< Y > &src)
\inmodule QtCore
const value_type & const_reference
operator bool() const noexcept
Returns true if the contained pointer is not \nullptr.
~QWeakPointer()
Destroys this QWeakPointer object.
bool operator!() const noexcept
Returns true if this object refers to \nullptr.
const value_type * const_pointer
bool isNull() const noexcept
Returns true if this object refers to \nullptr.
value_type * pointer
value_type & reference
QSharedPointer< X > copyAndSetPointer(X *ptr, const QSharedPointer< Y > &src)
void executeDeleter(T *t, Deleter d)
Q_CORE_EXPORT void internalSafetyCheckRemove(const void *)
void executeDeleter(T *t, RetVal(Klass::*memberDeleter)())
Q_CORE_EXPORT void internalSafetyCheckAdd(const void *, const volatile void *)
QSharedPointer< X > movePointer(X *ptr, QSharedPointer< Y > &&src)
T qobject_cast(const QObject *object)
Definition qobject.h:438
QSharedPointer< X > qSharedPointerConstCast(const QSharedPointer< T > &ptr)
Q_INLINE_TEMPLATE QSharedPointer< T >::difference_type operator-(const QSharedPointer< T > &ptr1, const QSharedPointer< X > &ptr2)
QSharedPointer< X > qSharedPointerObjectCast(QSharedPointer< T > &&ptr)
QSharedPointer< X > qSharedPointerCast(const QSharedPointer< T > &ptr)
QSharedPointer< typename QtSharedPointer::RemovePointer< X >::Type > qobject_cast(const QWeakPointer< T > &src)
QSharedPointer< X > qSharedPointerDynamicCast(const QSharedPointer< T > &ptr)
Q_DECLARE_TYPEINFO_BODY(QSharedPointer< T >, Q_RELOCATABLE_TYPE)
Q_INLINE_TEMPLATE QSharedPointer< T >::difference_type operator-(const QSharedPointer< T > &ptr1, X *ptr2)
QSharedPointer< typename QtSharedPointer::RemovePointer< X >::Type > qobject_cast(const QSharedPointer< T > &src)
QSharedPointer< typename QtSharedPointer::RemovePointer< X >::Type > qobject_cast(QSharedPointer< T > &&src)
Q_INLINE_TEMPLATE QSharedPointer< X >::difference_type operator-(T *ptr1, const QSharedPointer< X > &ptr2)
std::shared_ptr< X > qSharedPointerObjectCast(const std::shared_ptr< T > &src)
std::shared_ptr< X > qobject_pointer_cast(std::shared_ptr< T > &&src)
std::shared_ptr< X > qSharedPointerObjectCast(std::shared_ptr< T > &&src)
std::shared_ptr< X > qobject_pointer_cast(const std::shared_ptr< T > &src)
QSharedPointer< X > qSharedPointerStaticCast(QSharedPointer< T > &&ptr)
Q_DECLARE_TYPEINFO_BODY(QWeakPointer< T >, Q_RELOCATABLE_TYPE)
QSharedPointer< X > qSharedPointerStaticCast(const QSharedPointer< T > &ptr)
void swap(QWeakPointer< T > &p1, QWeakPointer< T > &p2) noexcept
QSharedPointer< X > qSharedPointerConstCast(QSharedPointer< T > &&ptr)
QSharedPointer< X > qSharedPointerDynamicCast(QSharedPointer< T > &&ptr)
QSharedPointer< X > qSharedPointerCast(QSharedPointer< T > &&ptr)
void swap(QSharedPointer< T > &p1, QSharedPointer< T > &p2) noexcept
QSharedPointer< X > qSharedPointerObjectCast(const QSharedPointer< T > &ptr)
static T * internalData(const QWeakPointer< T > &p) noexcept
void(* DestroyerFn)(ExternalRefCountData *)
void * operator new(std::size_t, void *ptr) noexcept
QT6_ONLY(Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable);) inline void checkQObjectShared(...)
static void deleter(ExternalRefCountData *self)
static ExternalRefCountData * create(NoCVType **ptr, DestroyerFn destroy)
static void safetyCheckDeleter(ExternalRefCountData *self)
static Self * create(T *ptr, Deleter userDeleter, DestroyerFn actualDeleter)
static void safetyCheckDeleter(ExternalRefCountData *self)
static void deleter(ExternalRefCountData *self)