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 : weakref{1}, strongref{1}, destroyer{d}
122 {
123 }
125 ~ExternalRefCountData() { Q_ASSERT(!weakref.loadRelaxed()); Q_ASSERT(strongref.loadRelaxed() <= 0); }
126
127 void destroy() { destroyer(this); }
128
129#ifndef QT_NO_QOBJECT
130 Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *);
132 Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable);
133 )
135#endif
136 inline void checkQObjectShared(...) { }
137 inline void setQObjectShared(...) { }
138
139 // Normally, only subclasses of ExternalRefCountData are allocated
140 // One exception exists in getAndRef; that uses the global operator new
141 // to prevent a mismatch with the custom operator delete
142 inline void *operator new(std::size_t) = delete;
143 // placement new
144 inline void *operator new(std::size_t, void *ptr) noexcept { return ptr; }
145 inline void operator delete(void *ptr) { ::operator delete(ptr); }
146 inline void operator delete(void *, void *) { }
147 };
148 // sizeof(ExternalRefCountData) = 12 (32-bit) / 16 (64-bit)
149
150 template <class T, typename Deleter>
152 {
153 Deleter deleter;
154 T *ptr;
155
156 CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {}
157 void execute() { executeDeleter(ptr, deleter); }
158 };
159 // sizeof(CustomDeleter) = sizeof(Deleter) + sizeof(void*) + padding
160 // for Deleter = stateless functor: 8 (32-bit) / 16 (64-bit) due to padding
161 // for Deleter = function pointer: 8 (32-bit) / 16 (64-bit)
162 // for Deleter = PMF: 12 (32-bit) / 24 (64-bit) (GCC)
163
164 // This specialization of CustomDeleter for a deleter of type NormalDeleter
165 // is an optimization: instead of storing a pointer to a function that does
166 // the deleting, we simply delete the pointer ourselves.
167 template <class T>
169 {
170 T *ptr;
171
173 void execute() { delete ptr; }
174 };
175 // sizeof(CustomDeleter specialization) = sizeof(void*)
176
177 // This class extends ExternalRefCountData and implements
178 // the static function that deletes the object. The pointer and the
179 // custom deleter are kept in the "extra" member so we can construct
180 // and destruct it independently of the full structure.
181 template <class T, typename Deleter>
183 {
186 CustomDeleter<T, Deleter> extra;
187
188 static inline void deleter(ExternalRefCountData *self)
189 {
190 Self *realself = static_cast<Self *>(self);
191 realself->extra.execute();
192
193 // delete the deleter too
194 realself->extra.~CustomDeleter<T, Deleter>();
195 }
197 {
199 deleter(self);
200 }
201
202 static inline Self *create(T *ptr, Deleter userDeleter, DestroyerFn actualDeleter)
203 {
204 Self *d = static_cast<Self *>(::operator new(sizeof(Self)));
205
206 // initialize the two sub-objects
207 new (&d->extra) CustomDeleter<T, Deleter>(ptr, userDeleter);
208 new (d) BaseClass(actualDeleter); // can't throw
209
210 return d;
211 }
212 private:
213 // prevent construction
214 ExternalRefCountWithCustomDeleter() = delete;
215 ~ExternalRefCountWithCustomDeleter() = delete;
217 };
218
219 // This class extends ExternalRefCountData and adds a "T"
220 // member. That way, when the create() function is called, we allocate
221 // memory for both QSharedPointer's d-pointer and the actual object being
222 // tracked.
223 template <class T>
225 {
227 typedef typename std::remove_cv<T>::type NoCVType;
229
230 static void deleter(ExternalRefCountData *self)
231 {
233 static_cast<ExternalRefCountWithContiguousData *>(self);
234 that->data.~T();
235 Q_UNUSED(that); // MSVC warns if T has a trivial destructor
236 }
238 {
240 deleter(self);
241 }
243
244 static inline ExternalRefCountData *create(NoCVType **ptr, DestroyerFn destroy)
245 {
247 static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData)));
248
249 // initialize the d-pointer sub-object
250 // leave d->data uninitialized
251 new (d) Parent(destroy); // can't throw
252
253 *ptr = &d->data;
254 return d;
255 }
256
257 private:
258 // prevent construction
259 ExternalRefCountWithContiguousData() = delete;
260 ~ExternalRefCountWithContiguousData() = delete;
262 };
263
264#ifndef QT_NO_QOBJECT
267#endif
268} // namespace QtSharedPointer
269
270template <class T> class QSharedPointer
271{
273 template <typename X>
274 using IfCompatible = typename std::enable_if<std::is_convertible<X*, T*>::value, bool>::type;
275
276public:
277 typedef T Type;
278 typedef T element_type;
279 typedef T value_type;
281 typedef const value_type *const_pointer;
285
286 T *data() const noexcept { return value.get(); }
287 T *get() const noexcept { return value.get(); }
288 bool isNull() const noexcept { return !data(); }
289 explicit operator bool() const noexcept { return !isNull(); }
290 bool operator !() const noexcept { return isNull(); }
291 T &operator*() const { return *data(); }
292 T *operator->() const noexcept { return data(); }
293
295 constexpr QSharedPointer() noexcept : value(nullptr), d(nullptr) { }
296 ~QSharedPointer() { deref(); }
297
299 constexpr QSharedPointer(std::nullptr_t) noexcept : value(nullptr), d(nullptr) { }
300
301 template <class X, IfCompatible<X> = true>
303 inline explicit QSharedPointer(X *ptr) : value(ptr) // noexcept
305
306 template <class X, typename Deleter, IfCompatible<X> = true>
310
311 template <typename Deleter>
314 { internalConstruct(static_cast<T *>(nullptr), deleter); }
315
318 { if (d) ref(); }
319 QSharedPointer &operator=(const QSharedPointer &other) noexcept
320 {
321 QSharedPointer copy(other);
322 swap(copy);
323 return *this;
324 }
327 : value(other.value.get()), d(other.d)
328 {
329 other.d = nullptr;
330 other.value = nullptr;
331 }
333
334 template <class X, IfCompatible<X> = true>
337 : value(other.value.get()), d(other.d)
338 {
339 other.d = nullptr;
340 other.value = nullptr;
341 }
342
343 template <class X, IfCompatible<X> = true>
345 {
347 swap(moved);
348 return *this;
349 }
350
351 template <class X, IfCompatible<X> = true>
354 { if (d) ref(); }
355
356 template <class X, IfCompatible<X> = true>
358 {
360 swap(copy);
361 return *this;
362 }
363
364 template <class X, IfCompatible<X> = true>
366 inline QSharedPointer(const QWeakPointer<X> &other) : value(nullptr), d(nullptr)
367 { *this = other; }
368
369 template <class X, IfCompatible<X> = true>
371 { internalSet(other.d, other.value); return *this; }
372
373 inline void swap(QSharedPointer &other) noexcept
374 { this->internalSwap(other); }
375
376 inline void reset() { clear(); }
377 inline void reset(T *t)
379 template <typename Deleter>
380 inline void reset(T *t, Deleter deleter)
382
383 template <class X>
385 {
386 return qSharedPointerStaticCast<X>(*this);
387 }
388
389 template <class X>
391 {
392 return qSharedPointerStaticCast<X>(std::move(*this));
393 }
394
395 template <class X>
397 {
398 return qSharedPointerDynamicCast<X>(*this);
399 }
400
401 template <class X>
403 {
404 return qSharedPointerDynamicCast<X>(std::move(*this));
405 }
406
407 template <class X>
409 {
410 return qSharedPointerConstCast<X>(*this);
411 }
412
413 template <class X>
415 {
416 return qSharedPointerConstCast<X>(std::move(*this));
417 }
418
419#ifndef QT_NO_QOBJECT
420 template <class X>
422 {
423 return qSharedPointerObjectCast<X>(*this);
424 }
425
426 template <class X>
428 {
429 return qSharedPointerObjectCast<X>(std::move(*this));
430 }
431#endif
432
433 inline void clear() { QSharedPointer copy; swap(copy); }
434
436
437 template <typename... Args>
438 [[nodiscard]] static QSharedPointer create(Args && ...arguments)
439 {
441# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
442 typename Private::DestroyerFn destroy = &Private::safetyCheckDeleter;
443# else
444 typename Private::DestroyerFn destroy = &Private::deleter;
445# endif
446 typename Private::DestroyerFn noDestroy = &Private::noDeleter;
447 QSharedPointer result(Qt::Uninitialized);
448 typename std::remove_cv<T>::type *ptr;
449 result.d = Private::create(&ptr, noDestroy);
450
451 // now initialize the data
452 new (ptr) T(std::forward<Args>(arguments)...);
453 result.value.reset(ptr);
454 result.d->destroyer = destroy;
455 result.d->setQObjectShared(result.value.get(), true);
456# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
457 internalSafetyCheckAdd(result.d, result.value.get());
458# endif
459 result.enableSharedFromThis(result.data());
460 return result;
461 }
462
463 template <typename X>
464 bool owner_before(const QSharedPointer<X> &other) const noexcept
465 { return std::less<>()(d, other.d); }
466 template <typename X>
467 bool owner_before(const QWeakPointer<X> &other) const noexcept
468 { return std::less<>()(d, other.d); }
469
470 template <typename X>
471 bool owner_equal(const QSharedPointer<X> &other) const noexcept
472 { return d == other.d; }
473 template <typename X>
474 bool owner_equal(const QWeakPointer<X> &other) const noexcept
475 { return d == other.d; }
476
477 size_t owner_hash() const noexcept
478 { return std::hash<Data *>()(d); }
479
480private:
481 template <typename X>
482 friend bool comparesEqual(const QSharedPointer &lhs, const QSharedPointer<X> &rhs) noexcept
483 { return lhs.data() == rhs.data(); }
484 template <typename X>
485 friend Qt::strong_ordering
486 compareThreeWay(const QSharedPointer &lhs, const QSharedPointer<X> &rhs) noexcept
487 {
488 return Qt::compareThreeWay(lhs.value, rhs.data());
489 }
490 QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, QSharedPointer<T>, QSharedPointer<X>,
491 /* non-constexpr */, noexcept(true),
492 template <typename X>)
493
494 template <typename X>
495 friend bool comparesEqual(const QSharedPointer &lhs, X *rhs) noexcept
496 { return lhs.data() == rhs; }
497 template <typename X>
499 { return Qt::compareThreeWay(lhs.value, rhs); }
500 Q_DECLARE_STRONGLY_ORDERED(QSharedPointer, X*, template <typename X>)
501
502 friend bool comparesEqual(const QSharedPointer &lhs, std::nullptr_t) noexcept
503 { return lhs.data() == nullptr; }
504 friend Qt::strong_ordering
506 { return Qt::compareThreeWay(lhs.value, nullptr); }
508
510 explicit QSharedPointer(Qt::Initialization) {}
511
512 void deref() noexcept
513 { deref(d); }
514 static void deref(Data *dd) noexcept
515 {
516 if (!dd) return;
517 if (!dd->strongref.deref()) {
518 dd->destroy();
519 }
520 if (!dd->weakref.deref())
521 delete dd;
522 }
523
524 template <class X>
526 {
528 }
529
530 inline void enableSharedFromThis(...) {}
531
532 template <typename X, typename Deleter>
533 inline void internalConstruct(X *ptr, Deleter deleter)
534 {
536# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
538# else
540# endif
542
543#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
545#endif
547 }
548
549 void internalSwap(QSharedPointer &other) noexcept
550 {
553 }
554
555 template <class X> friend class QSharedPointer;
556 template <class X> friend class QWeakPointer;
557 template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
558 template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::movePointer(X * ptr, QSharedPointer<Y> &&src);
559 void ref() const noexcept { d->weakref.ref(); d->strongref.ref(); }
560
561 inline void internalSet(Data *o, T *actual)
562 {
563 if (o) {
564 // increase the strongref, but never up from zero
565 // or less (-1 is used by QWeakPointer on untracked QObject)
566 int tmp = o->strongref.loadRelaxed();
567 while (tmp > 0) {
568 // try to increment from "tmp" to "tmp + 1"
569 if (o->strongref.testAndSetRelaxed(tmp, tmp + 1))
570 break; // succeeded
571 tmp = o->strongref.loadRelaxed(); // failed, try again
572 }
573
574 if (tmp > 0)
575 o->weakref.ref();
576 else
577 o = nullptr;
578 }
579
580 qt_ptr_swap(d, o);
581 this->value.reset(actual);
582 if (!d || d->strongref.loadRelaxed() == 0)
583 this->value = nullptr;
584
585 // dereference saved data
586 deref(o);
587 }
588
589 Qt::totally_ordered_wrapper<Type *> value;
590 Data *d;
591};
592
593template <class T>
595{
597 template <typename X>
599 std::negation<std::is_same<T, X>>, // don't make accidental copy/move SMFs
600 std::is_convertible<X*, T*>
601 >, bool>;
602
603 template <typename X>
604 using IfVirtualBase = typename std::enable_if<qxp::is_virtual_base_of_v<T, X>, bool>::type;
605
606 template <typename X>
607 using IfNotVirtualBase = typename std::enable_if<!qxp::is_virtual_base_of_v<T, X>, bool>::type;
608
609public:
610 typedef T element_type;
611 typedef T value_type;
613 typedef const value_type *const_pointer;
617
618 bool isNull() const noexcept { return d == nullptr || d->strongref.loadRelaxed() == 0 || value == nullptr; }
619 explicit operator bool() const noexcept { return !isNull(); }
620 bool operator !() const noexcept { return isNull(); }
621
623 constexpr QWeakPointer() noexcept : d(nullptr), value(nullptr) { }
624 inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
625
628 { if (d) d->weakref.ref(); }
631 : d(other.d), value(other.value)
632 {
633 other.d = nullptr;
634 other.value = nullptr;
635 }
637
638 template <class X, IfCompatible<X> = true, IfNotVirtualBase<X> = true>
641 : d(std::exchange(other.d, nullptr)),
642 value(std::exchange(other.value, nullptr))
643 {
644 }
645
646 template <class X, IfCompatible<X> = true, IfVirtualBase<X> = true>
649 : d(other.d), value(other.toStrongRef().get()) // must go through QSharedPointer, see below
650 {
651 other.d = nullptr;
652 other.value = nullptr;
653 }
654
655 template <class X, IfCompatible<X> = true>
657 {
659 swap(moved);
660 return *this;
661 }
662
664 {
666 swap(copy);
667 return *this;
668 }
669
670 void swap(QWeakPointer &other) noexcept
671 {
672 qt_ptr_swap(this->d, other.d);
674 }
675
677 inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data())
678 { if (d) d->weakref.ref();}
680 {
681 internalSet(o.d, o.value.get());
682 return *this;
683 }
684
685 template <class X, IfCompatible<X> = true>
687 inline QWeakPointer(const QWeakPointer<X> &o) : d(nullptr), value(nullptr)
688 { *this = o; }
689
690 template <class X, IfCompatible<X> = true>
692 {
693 // conversion between X and T could require access to the virtual table
694 // so force the operation to go through QSharedPointer
695 *this = o.toStrongRef();
696 return *this;
697 }
698
699 template <class X, IfCompatible<X> = true>
701 inline QWeakPointer(const QSharedPointer<X> &o) : d(nullptr), value(nullptr)
702 { *this = o; }
703
704 template <class X, IfCompatible<X> = true>
706 {
707 internalSet(o.d, o.data());
708 return *this;
709 }
710
711 inline void clear() { *this = QWeakPointer(); }
712
713 [[nodiscard]] QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
714 // std::weak_ptr compatibility:
715 [[nodiscard]] QSharedPointer<T> lock() const { return toStrongRef(); }
716
717 template <class X>
718 bool operator==(const QWeakPointer<X> &o) const noexcept
719 { return d == o.d && value == static_cast<const T *>(o.value); }
720
721 template <class X>
722 bool operator!=(const QWeakPointer<X> &o) const noexcept
723 { return !(*this == o); }
724
725 template <class X>
726 bool operator==(const QSharedPointer<X> &o) const noexcept
727 { return d == o.d; }
728
729 template <class X>
730 bool operator!=(const QSharedPointer<X> &o) const noexcept
731 { return !(*this == o); }
732
733 template <typename X>
734 friend bool operator==(const QSharedPointer<X> &p1, const QWeakPointer &p2) noexcept
735 { return p2 == p1; }
736 template <typename X>
737 friend bool operator!=(const QSharedPointer<X> &p1, const QWeakPointer &p2) noexcept
738 { return p2 != p1; }
739
740 friend bool operator==(const QWeakPointer &p, std::nullptr_t)
741 { return p.isNull(); }
742 friend bool operator==(std::nullptr_t, const QWeakPointer &p)
743 { return p.isNull(); }
744 friend bool operator!=(const QWeakPointer &p, std::nullptr_t)
745 { return !p.isNull(); }
746 friend bool operator!=(std::nullptr_t, const QWeakPointer &p)
747 { return !p.isNull(); }
748
749 template <typename X>
750 bool owner_before(const QWeakPointer<X> &other) const noexcept
751 { return std::less<>()(d, other.d); }
752 template <typename X>
753 bool owner_before(const QSharedPointer<X> &other) const noexcept
754 { return std::less<>()(d, other.d); }
755
756 template <typename X>
757 bool owner_equal(const QWeakPointer<X> &other) const noexcept
758 { return d == other.d; }
759 template <typename X>
760 bool owner_equal(const QSharedPointer<X> &other) const noexcept
761 { return d == other.d; }
762
763 size_t owner_hash() const noexcept
764 { return std::hash<Data *>()(d); }
765
766private:
768 template <class X> friend class QSharedPointer;
769 template <class X> friend class QWeakPointer;
770 template <class X> friend class QPointer;
771
772 template <class X>
773 inline QWeakPointer &assign(X *ptr)
774 { return *this = QWeakPointer<T>(ptr, true); }
775
776#ifndef QT_NO_QOBJECT
778 QWeakPointer(T *ptr, bool)
779 : d{ptr ? Data::getAndRef(ptr) : nullptr}, value{ptr}
780 { }
781
782 template <class X, IfCompatible<X> = true>
784 inline QWeakPointer(X *ptr, bool) : d(ptr ? Data::getAndRef(ptr) : nullptr), value(ptr)
785 { }
786#endif
787
788 inline void internalSet(Data *o, T *actual)
789 {
790 if (d == o) return;
791 if (o)
792 o->weakref.ref();
793 if (d && !d->weakref.deref())
794 delete d;
795 d = o;
796 value = actual;
797 }
798
799 // ### TODO - QTBUG-88102: remove all users of this API; no one should ever
800 // access a weak pointer's data but the weak pointer itself
801 inline T *internalData() const noexcept
802 {
803 return d == nullptr || d->strongref.loadRelaxed() == 0 ? nullptr : value;
804 }
805
806 Data *d;
807 T *value;
808};
809
810namespace QtPrivate {
812 template <typename T>
813 static T *internalData(const QWeakPointer<T> &p) noexcept { return p.internalData(); }
814};
815// hack to delay name lookup to instantiation time by making
816// EnableInternalData a dependent name:
817template <typename T>
819}
820
821template <class T>
823{
824protected:
828
829public:
830 inline QSharedPointer<T> sharedFromThis() { return QSharedPointer<T>(weakPointer); }
831 inline QSharedPointer<const T> sharedFromThis() const { return QSharedPointer<const T>(weakPointer); }
832
833private:
834 template <class X> friend class QSharedPointer;
835 template <class X>
836 inline void initializeFromSharedPointer(const QSharedPointer<X> &ptr) const
837 {
838 weakPointer = ptr;
839 }
840
841 mutable QWeakPointer<T> weakPointer;
842};
843
844//
845// operator-
846//
847template <class T, class X>
849{
850 return ptr1.data() - ptr2.data();
851}
852template <class T, class X>
854{
855 return ptr1.data() - ptr2;
856}
857template <class T, class X>
859{
860 return ptr1 - ptr2.data();
861}
862
863//
864// qHash
865//
866template <class T>
867Q_INLINE_TEMPLATE size_t qHash(const QSharedPointer<T> &ptr, size_t seed = 0)
868{
869 return qHash(ptr.data(), seed);
870}
871
872
873template <class T>
874Q_INLINE_TEMPLATE QWeakPointer<T> QSharedPointer<T>::toWeakRef() const
875{
876 return QWeakPointer<T>(*this);
877}
878
879template <class T>
880inline void swap(QSharedPointer<T> &p1, QSharedPointer<T> &p2) noexcept
881{ p1.swap(p2); }
882
883template <class T>
884inline void swap(QWeakPointer<T> &p1, QWeakPointer<T> &p2) noexcept
885{ p1.swap(p2); }
886
887namespace QtSharedPointer {
888// helper functions:
889 template <class X, class T>
896
897 template <class X, class T>
899 {
901 result.d = std::exchange(src.d, nullptr);
903 src.value.reset(nullptr);
904 return result;
905 }
906}
907
908// cast operators
909template <class X, class T>
910Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &src)
911{
912 return qSharedPointerStaticCast<X>(src);
913}
914template <class X, class T>
915Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(QSharedPointer<T> &&src)
916{
917 return qSharedPointerStaticCast<X>(std::move(src));
918}
919template <class X, class T>
920Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &src)
921{
922 return qSharedPointerCast<X>(src.toStrongRef());
923}
924template <class X, class T>
925Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerStaticCast(const QSharedPointer<T> &src)
926{
927 X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
928 return QtSharedPointer::copyAndSetPointer(ptr, src);
929}
930template <class X, class T>
931Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerStaticCast(QSharedPointer<T> &&src)
932{
933 X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
934 return QtSharedPointer::movePointer(ptr, std::move(src));
935}
936template <class X, class T>
937Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerStaticCast(const QWeakPointer<T> &src)
938{
939 return qSharedPointerStaticCast<X>(src.toStrongRef());
940}
941
942template <class X, class T>
943Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src)
944{
945 X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
946 if (!ptr)
947 return QSharedPointer<X>();
948 return QtSharedPointer::copyAndSetPointer(ptr, src);
949}
950template <class X, class T>
951Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(QSharedPointer<T> &&src)
952{
953 X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
954 if (!ptr)
955 return QSharedPointer<X>();
956 return QtSharedPointer::movePointer(ptr, std::move(src));
957}
958template <class X, class T>
959Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src)
960{
961 return qSharedPointerDynamicCast<X>(src.toStrongRef());
962}
963
964template <class X, class T>
965Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src)
966{
967 X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
968 return QtSharedPointer::copyAndSetPointer(ptr, src);
969}
970template <class X, class T>
971Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(QSharedPointer<T> &&src)
972{
973 X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
974 return QtSharedPointer::movePointer(ptr, std::move(src));
975}
976template <class X, class T>
977Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src)
978{
979 return qSharedPointerConstCast<X>(src.toStrongRef());
980}
981
982template <class X, class T>
983Q_INLINE_TEMPLATE
984QWeakPointer<X> qWeakPointerCast(const QSharedPointer<T> &src)
985{
986 return qSharedPointerCast<X>(src).toWeakRef();
987}
988
989#ifndef QT_NO_QOBJECT
990template <class X, class T>
991Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src)
992{
993 X *ptr = qobject_cast<X *>(src.data());
994 if (!ptr)
995 return QSharedPointer<X>();
996 return QtSharedPointer::copyAndSetPointer(ptr, src);
997}
998template <class X, class T>
999Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(QSharedPointer<T> &&src)
1000{
1001 X *ptr = qobject_cast<X *>(src.data());
1002 if (!ptr)
1003 return QSharedPointer<X>();
1004 return QtSharedPointer::movePointer(ptr, std::move(src));
1005}
1006template <class X, class T>
1007Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src)
1008{
1009 return qSharedPointerObjectCast<X>(src.toStrongRef());
1010}
1011
1012template <class X, class T>
1015{
1016 return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type>(src);
1017}
1018template <class X, class T>
1021{
1022 return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type>(std::move(src));
1023}
1024template <class X, class T>
1027{
1028 return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type>(src);
1029}
1030
1031/// ### TODO - QTBUG-88102: make this use toStrongRef() (once support for
1032/// storing non-managed QObjects in QWeakPointer is removed)
1033template<typename T>
1034QWeakPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
1035qWeakPointerFromVariant(const QVariant &variant)
1036{
1037 return QWeakPointer<T>(qobject_cast<T*>(QtPrivate::EnableInternalData::internalData(QtSharedPointer::weakPointerFromVariant_internal(variant))));
1038}
1039template<typename T>
1040QSharedPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
1041qSharedPointerFromVariant(const QVariant &variant)
1042{
1043 return qSharedPointerObjectCast<T>(QtSharedPointer::sharedPointerFromVariant_internal(variant));
1044}
1045
1046// std::shared_ptr helpers
1047
1048template <typename X, class T>
1049std::shared_ptr<X> qobject_pointer_cast(const std::shared_ptr<T> &src)
1050{
1051 using element_type = typename std::shared_ptr<X>::element_type;
1052 if (auto ptr = qobject_cast<element_type *>(src.get()))
1053 return std::shared_ptr<X>(src, ptr);
1054 return std::shared_ptr<X>();
1055}
1056
1057template <typename X, class T>
1058std::shared_ptr<X> qobject_pointer_cast(std::shared_ptr<T> &&src)
1059{
1060 using element_type = typename std::shared_ptr<X>::element_type;
1061 auto castResult = qobject_cast<element_type *>(src.get());
1062 if (castResult) {
1063 // C++2a's move aliasing constructor will leave src empty.
1064 // Before C++2a we don't really know if the compiler has support for it.
1065 // The move aliasing constructor is the resolution for LWG2996,
1066 // which does not impose a feature-testing macro. So: clear src.
1067 return std::shared_ptr<X>(std::exchange(src, nullptr), castResult);
1068 }
1069 return std::shared_ptr<X>();
1070}
1071
1072template <typename X, class T>
1073std::shared_ptr<X> qSharedPointerObjectCast(const std::shared_ptr<T> &src)
1074{
1075 return qobject_pointer_cast<X>(src);
1076}
1077
1078template <typename X, class T>
1079std::shared_ptr<X> qSharedPointerObjectCast(std::shared_ptr<T> &&src)
1080{
1081 return qobject_pointer_cast<X>(std::move(src));
1082}
1083
1084#endif
1085
1088
1089
1090QT_END_NAMESPACE
1091
1092#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)