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>
63
64#ifndef QT_NO_QOBJECT
65template <class X, class T>
67template <class X, class T>
69#endif
70
71namespace QtPrivate {
73}
74
75namespace QtSharedPointer {
76 template <class T> class ExternalRefCount;
77
78 template <class X, class Y> QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
79 template <class X, class Y> QSharedPointer<X> movePointer(X * ptr, QSharedPointer<Y> &&src);
80
81 // used in debug mode to verify the reuse of pointers
82 Q_CORE_EXPORT void internalSafetyCheckAdd(const void *, const volatile void *);
84
85 template <class T, typename Klass, typename RetVal>
86 inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)())
87 { if (t) (t->*memberDeleter)(); }
88 template <class T, typename Deleter>
89 inline void executeDeleter(T *t, Deleter d)
90 { d(t); }
91 struct NormalDeleter {};
92
93 // this uses partial template specialization
94 template <class T> struct RemovePointer;
95 template <class T> struct RemovePointer<T *> { typedef T Type; };
96 template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; };
97 template <class T> struct RemovePointer<QWeakPointer<T> > { typedef T Type; };
98
99 // This class is the d-pointer of QSharedPointer and QWeakPointer.
100 //
101 // It is a reference-counted reference counter. "strongref" is the inner
102 // reference counter, and it tracks the lifetime of the pointer itself.
103 // "weakref" is the outer reference counter and it tracks the lifetime of
104 // the ExternalRefCountData object.
105 //
106 // The deleter is stored in the destroyer member and is always a pointer to
107 // a static function in ExternalRefCountWithCustomDeleter or in
108 // ExternalRefCountWithContiguousData
110 {
115
117 : destroyer(d)
118 {
119 strongref.storeRelaxed(1);
120 weakref.storeRelaxed(1);
121 }
123 ~ExternalRefCountData() { Q_ASSERT(!weakref.loadRelaxed()); Q_ASSERT(strongref.loadRelaxed() <= 0); }
124
125 void destroy() { destroyer(this); }
126
127#ifndef QT_NO_QOBJECT
128 Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *);
130 Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable);
131 )
133#endif
134 inline void checkQObjectShared(...) { }
135 inline void setQObjectShared(...) { }
136
137 // Normally, only subclasses of ExternalRefCountData are allocated
138 // One exception exists in getAndRef; that uses the global operator new
139 // to prevent a mismatch with the custom operator delete
140 inline void *operator new(std::size_t) = delete;
141 // placement new
142 inline void *operator new(std::size_t, void *ptr) noexcept { return ptr; }
143 inline void operator delete(void *ptr) { ::operator delete(ptr); }
144 inline void operator delete(void *, void *) { }
145 };
146 // sizeof(ExternalRefCountData) = 12 (32-bit) / 16 (64-bit)
147
148 template <class T, typename Deleter>
150 {
151 Deleter deleter;
152 T *ptr;
153
154 CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {}
155 void execute() { executeDeleter(ptr, deleter); }
156 };
157 // sizeof(CustomDeleter) = sizeof(Deleter) + sizeof(void*) + padding
158 // for Deleter = stateless functor: 8 (32-bit) / 16 (64-bit) due to padding
159 // for Deleter = function pointer: 8 (32-bit) / 16 (64-bit)
160 // for Deleter = PMF: 12 (32-bit) / 24 (64-bit) (GCC)
161
162 // This specialization of CustomDeleter for a deleter of type NormalDeleter
163 // is an optimization: instead of storing a pointer to a function that does
164 // the deleting, we simply delete the pointer ourselves.
165 template <class T>
167 {
168 T *ptr;
169
171 void execute() { delete ptr; }
172 };
173 // sizeof(CustomDeleter specialization) = sizeof(void*)
174
175 // This class extends ExternalRefCountData and implements
176 // the static function that deletes the object. The pointer and the
177 // custom deleter are kept in the "extra" member so we can construct
178 // and destruct it independently of the full structure.
179 template <class T, typename Deleter>
181 {
184 CustomDeleter<T, Deleter> extra;
185
186 static inline void deleter(ExternalRefCountData *self)
187 {
188 Self *realself = static_cast<Self *>(self);
189 realself->extra.execute();
190
191 // delete the deleter too
192 realself->extra.~CustomDeleter<T, Deleter>();
193 }
195 {
197 deleter(self);
198 }
199
200 static inline Self *create(T *ptr, Deleter userDeleter, DestroyerFn actualDeleter)
201 {
202 Self *d = static_cast<Self *>(::operator new(sizeof(Self)));
203
204 // initialize the two sub-objects
205 new (&d->extra) CustomDeleter<T, Deleter>(ptr, userDeleter);
206 new (d) BaseClass(actualDeleter); // can't throw
207
208 return d;
209 }
210 private:
211 // prevent construction
212 ExternalRefCountWithCustomDeleter() = delete;
213 ~ExternalRefCountWithCustomDeleter() = delete;
215 };
216
217 // This class extends ExternalRefCountData and adds a "T"
218 // member. That way, when the create() function is called, we allocate
219 // memory for both QSharedPointer's d-pointer and the actual object being
220 // tracked.
221 template <class T>
223 {
225 typedef typename std::remove_cv<T>::type NoCVType;
227
228 static void deleter(ExternalRefCountData *self)
229 {
231 static_cast<ExternalRefCountWithContiguousData *>(self);
232 that->data.~T();
233 Q_UNUSED(that); // MSVC warns if T has a trivial destructor
234 }
236 {
238 deleter(self);
239 }
241
242 static inline ExternalRefCountData *create(NoCVType **ptr, DestroyerFn destroy)
243 {
245 static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData)));
246
247 // initialize the d-pointer sub-object
248 // leave d->data uninitialized
249 new (d) Parent(destroy); // can't throw
250
251 *ptr = &d->data;
252 return d;
253 }
254
255 private:
256 // prevent construction
257 ExternalRefCountWithContiguousData() = delete;
258 ~ExternalRefCountWithContiguousData() = delete;
260 };
261
262#ifndef QT_NO_QOBJECT
265#endif
266} // namespace QtSharedPointer
267
268template <class T> class QSharedPointer
269{
271 template <typename X>
272 using IfCompatible = typename std::enable_if<std::is_convertible<X*, T*>::value, bool>::type;
273
274public:
275 typedef T Type;
276 typedef T element_type;
277 typedef T value_type;
279 typedef const value_type *const_pointer;
283
284 T *data() const noexcept { return value.get(); }
285 T *get() const noexcept { return value.get(); }
286 bool isNull() const noexcept { return !data(); }
287 explicit operator bool() const noexcept { return !isNull(); }
288 bool operator !() const noexcept { return isNull(); }
289 T &operator*() const { return *data(); }
290 T *operator->() const noexcept { return data(); }
291
293 constexpr QSharedPointer() noexcept : value(nullptr), d(nullptr) { }
294 ~QSharedPointer() { deref(); }
295
297 constexpr QSharedPointer(std::nullptr_t) noexcept : value(nullptr), d(nullptr) { }
298
299 template <class X, IfCompatible<X> = true>
301 inline explicit QSharedPointer(X *ptr) : value(ptr) // noexcept
303
304 template <class X, typename Deleter, IfCompatible<X> = true>
308
309 template <typename Deleter>
312 { internalConstruct(static_cast<T *>(nullptr), deleter); }
313
316 { if (d) ref(); }
317 QSharedPointer &operator=(const QSharedPointer &other) noexcept
318 {
319 QSharedPointer copy(other);
320 swap(copy);
321 return *this;
322 }
325 : value(other.value.get()), d(other.d)
326 {
327 other.d = nullptr;
328 other.value = nullptr;
329 }
331
332 template <class X, IfCompatible<X> = true>
335 : value(other.value.get()), d(other.d)
336 {
337 other.d = nullptr;
338 other.value = nullptr;
339 }
340
341 template <class X, IfCompatible<X> = true>
343 {
345 swap(moved);
346 return *this;
347 }
348
349 template <class X, IfCompatible<X> = true>
352 { if (d) ref(); }
353
354 template <class X, IfCompatible<X> = true>
356 {
358 swap(copy);
359 return *this;
360 }
361
362 template <class X, IfCompatible<X> = true>
364 inline QSharedPointer(const QWeakPointer<X> &other) : value(nullptr), d(nullptr)
365 { *this = other; }
366
367 template <class X, IfCompatible<X> = true>
369 { internalSet(other.d, other.value); return *this; }
370
371 inline void swap(QSharedPointer &other) noexcept
372 { this->internalSwap(other); }
373
374 inline void reset() { clear(); }
375 inline void reset(T *t)
377 template <typename Deleter>
378 inline void reset(T *t, Deleter deleter)
380
381 template <class X>
383 {
384 return qSharedPointerCast<X>(*this);
385 }
386
387 template <class X>
389 {
390 return qSharedPointerCast<X>(std::move(*this));
391 }
392
393 template <class X>
395 {
396 return qSharedPointerDynamicCast<X>(*this);
397 }
398
399 template <class X>
401 {
402 return qSharedPointerDynamicCast<X>(std::move(*this));
403 }
404
405 template <class X>
407 {
408 return qSharedPointerConstCast<X>(*this);
409 }
410
411 template <class X>
413 {
414 return qSharedPointerConstCast<X>(std::move(*this));
415 }
416
417#ifndef QT_NO_QOBJECT
418 template <class X>
420 {
421 return qSharedPointerObjectCast<X>(*this);
422 }
423
424 template <class X>
426 {
427 return qSharedPointerObjectCast<X>(std::move(*this));
428 }
429#endif
430
431 inline void clear() { QSharedPointer copy; swap(copy); }
432
434
435 template <typename... Args>
436 [[nodiscard]] static QSharedPointer create(Args && ...arguments)
437 {
439# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
440 typename Private::DestroyerFn destroy = &Private::safetyCheckDeleter;
441# else
442 typename Private::DestroyerFn destroy = &Private::deleter;
443# endif
444 typename Private::DestroyerFn noDestroy = &Private::noDeleter;
445 QSharedPointer result(Qt::Uninitialized);
446 typename std::remove_cv<T>::type *ptr;
447 result.d = Private::create(&ptr, noDestroy);
448
449 // now initialize the data
450 new (ptr) T(std::forward<Args>(arguments)...);
451 result.value.reset(ptr);
452 result.d->destroyer = destroy;
453 result.d->setQObjectShared(result.value.get(), true);
454# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
455 internalSafetyCheckAdd(result.d, result.value.get());
456# endif
457 result.enableSharedFromThis(result.data());
458 return result;
459 }
460
461 template <typename X>
462 bool owner_before(const QSharedPointer<X> &other) const noexcept
463 { return std::less<>()(d, other.d); }
464 template <typename X>
465 bool owner_before(const QWeakPointer<X> &other) const noexcept
466 { return std::less<>()(d, other.d); }
467
468 template <typename X>
469 bool owner_equal(const QSharedPointer<X> &other) const noexcept
470 { return d == other.d; }
471 template <typename X>
472 bool owner_equal(const QWeakPointer<X> &other) const noexcept
473 { return d == other.d; }
474
475 size_t owner_hash() const noexcept
476 { return std::hash<Data *>()(d); }
477
478private:
479 template <typename X>
480 friend bool comparesEqual(const QSharedPointer &lhs, const QSharedPointer<X> &rhs) noexcept
481 { return lhs.data() == rhs.data(); }
482 template <typename X>
483 friend Qt::strong_ordering
484 compareThreeWay(const QSharedPointer &lhs, const QSharedPointer<X> &rhs) noexcept
485 {
486 return Qt::compareThreeWay(lhs.value, rhs.data());
487 }
488 QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, QSharedPointer<T>, QSharedPointer<X>,
489 /* non-constexpr */, noexcept(true),
490 template <typename X>)
491
492 template <typename X>
493 friend bool comparesEqual(const QSharedPointer &lhs, X *rhs) noexcept
494 { return lhs.data() == rhs; }
495 template <typename X>
497 { return Qt::compareThreeWay(lhs.value, rhs); }
498 Q_DECLARE_STRONGLY_ORDERED(QSharedPointer, X*, template <typename X>)
499
500 friend bool comparesEqual(const QSharedPointer &lhs, std::nullptr_t) noexcept
501 { return lhs.data() == nullptr; }
502 friend Qt::strong_ordering
504 { return Qt::compareThreeWay(lhs.value, nullptr); }
506
508 explicit QSharedPointer(Qt::Initialization) {}
509
510 void deref() noexcept
511 { deref(d); }
512 static void deref(Data *dd) noexcept
513 {
514 if (!dd) return;
515 if (!dd->strongref.deref()) {
516 dd->destroy();
517 }
518 if (!dd->weakref.deref())
519 delete dd;
520 }
521
522 template <class X>
524 {
526 }
527
528 inline void enableSharedFromThis(...) {}
529
530 template <typename X, typename Deleter>
531 inline void internalConstruct(X *ptr, Deleter deleter)
532 {
534# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
536# else
538# endif
540
541#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
543#endif
545 }
546
547 void internalSwap(QSharedPointer &other) noexcept
548 {
551 }
552
553 template <class X> friend class QSharedPointer;
554 template <class X> friend class QWeakPointer;
555 template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
556 template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::movePointer(X * ptr, QSharedPointer<Y> &&src);
557 void ref() const noexcept { d->weakref.ref(); d->strongref.ref(); }
558
559 inline void internalSet(Data *o, T *actual)
560 {
561 if (o) {
562 // increase the strongref, but never up from zero
563 // or less (-1 is used by QWeakPointer on untracked QObject)
564 int tmp = o->strongref.loadRelaxed();
565 while (tmp > 0) {
566 // try to increment from "tmp" to "tmp + 1"
567 if (o->strongref.testAndSetRelaxed(tmp, tmp + 1))
568 break; // succeeded
569 tmp = o->strongref.loadRelaxed(); // failed, try again
570 }
571
572 if (tmp > 0)
573 o->weakref.ref();
574 else
575 o = nullptr;
576 }
577
578 qt_ptr_swap(d, o);
579 this->value.reset(actual);
580 if (!d || d->strongref.loadRelaxed() == 0)
581 this->value = nullptr;
582
583 // dereference saved data
584 deref(o);
585 }
586
587 Qt::totally_ordered_wrapper<Type *> value;
588 Data *d;
589};
590
591template <class T>
593{
595 template <typename X>
597 std::negation<std::is_same<T, X>>, // don't make accidental copy/move SMFs
598 std::is_convertible<X*, T*>
599 >, bool>;
600
601 template <typename X>
602 using IfVirtualBase = typename std::enable_if<qxp::is_virtual_base_of_v<T, X>, bool>::type;
603
604 template <typename X>
605 using IfNotVirtualBase = typename std::enable_if<!qxp::is_virtual_base_of_v<T, X>, bool>::type;
606
607public:
608 typedef T element_type;
609 typedef T value_type;
611 typedef const value_type *const_pointer;
615
616 bool isNull() const noexcept { return d == nullptr || d->strongref.loadRelaxed() == 0 || value == nullptr; }
617 explicit operator bool() const noexcept { return !isNull(); }
618 bool operator !() const noexcept { return isNull(); }
619
621 constexpr QWeakPointer() noexcept : d(nullptr), value(nullptr) { }
622 inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
623
626 { if (d) d->weakref.ref(); }
629 : d(other.d), value(other.value)
630 {
631 other.d = nullptr;
632 other.value = nullptr;
633 }
635
636 template <class X, IfCompatible<X> = true, IfNotVirtualBase<X> = true>
639 : d(std::exchange(other.d, nullptr)),
640 value(std::exchange(other.value, nullptr))
641 {
642 }
643
644 template <class X, IfCompatible<X> = true, IfVirtualBase<X> = true>
647 : d(other.d), value(other.toStrongRef().get()) // must go through QSharedPointer, see below
648 {
649 other.d = nullptr;
650 other.value = nullptr;
651 }
652
653 template <class X, IfCompatible<X> = true>
655 {
657 swap(moved);
658 return *this;
659 }
660
662 {
664 swap(copy);
665 return *this;
666 }
667
668 void swap(QWeakPointer &other) noexcept
669 {
670 qt_ptr_swap(this->d, other.d);
672 }
673
675 inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data())
676 { if (d) d->weakref.ref();}
678 {
679 internalSet(o.d, o.value.get());
680 return *this;
681 }
682
683 template <class X, IfCompatible<X> = true>
685 inline QWeakPointer(const QWeakPointer<X> &o) : d(nullptr), value(nullptr)
686 { *this = o; }
687
688 template <class X, IfCompatible<X> = true>
690 {
691 // conversion between X and T could require access to the virtual table
692 // so force the operation to go through QSharedPointer
693 *this = o.toStrongRef();
694 return *this;
695 }
696
697 template <class X, IfCompatible<X> = true>
699 inline QWeakPointer(const QSharedPointer<X> &o) : d(nullptr), value(nullptr)
700 { *this = o; }
701
702 template <class X, IfCompatible<X> = true>
704 {
705 internalSet(o.d, o.data());
706 return *this;
707 }
708
709 inline void clear() { *this = QWeakPointer(); }
710
711 [[nodiscard]] QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
712 // std::weak_ptr compatibility:
713 [[nodiscard]] QSharedPointer<T> lock() const { return toStrongRef(); }
714
715 template <class X>
716 bool operator==(const QWeakPointer<X> &o) const noexcept
717 { return d == o.d && value == static_cast<const T *>(o.value); }
718
719 template <class X>
720 bool operator!=(const QWeakPointer<X> &o) const noexcept
721 { return !(*this == o); }
722
723 template <class X>
724 bool operator==(const QSharedPointer<X> &o) const noexcept
725 { return d == o.d; }
726
727 template <class X>
728 bool operator!=(const QSharedPointer<X> &o) const noexcept
729 { return !(*this == o); }
730
731 template <typename X>
732 friend bool operator==(const QSharedPointer<X> &p1, const QWeakPointer &p2) noexcept
733 { return p2 == p1; }
734 template <typename X>
735 friend bool operator!=(const QSharedPointer<X> &p1, const QWeakPointer &p2) noexcept
736 { return p2 != p1; }
737
738 friend bool operator==(const QWeakPointer &p, std::nullptr_t)
739 { return p.isNull(); }
740 friend bool operator==(std::nullptr_t, const QWeakPointer &p)
741 { return p.isNull(); }
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
747 template <typename X>
748 bool owner_before(const QWeakPointer<X> &other) const noexcept
749 { return std::less<>()(d, other.d); }
750 template <typename X>
751 bool owner_before(const QSharedPointer<X> &other) const noexcept
752 { return std::less<>()(d, other.d); }
753
754 template <typename X>
755 bool owner_equal(const QWeakPointer<X> &other) const noexcept
756 { return d == other.d; }
757 template <typename X>
758 bool owner_equal(const QSharedPointer<X> &other) const noexcept
759 { return d == other.d; }
760
761 size_t owner_hash() const noexcept
762 { return std::hash<Data *>()(d); }
763
764private:
766 template <class X> friend class QSharedPointer;
767 template <class X> friend class QWeakPointer;
768 template <class X> friend class QPointer;
769
770 template <class X>
771 inline QWeakPointer &assign(X *ptr)
772 { return *this = QWeakPointer<T>(ptr, true); }
773
774#ifndef QT_NO_QOBJECT
776 QWeakPointer(T *ptr, bool)
777 : d{ptr ? Data::getAndRef(ptr) : nullptr}, value{ptr}
778 { }
779
780 template <class X, IfCompatible<X> = true>
782 inline QWeakPointer(X *ptr, bool) : d(ptr ? Data::getAndRef(ptr) : nullptr), value(ptr)
783 { }
784#endif
785
786 inline void internalSet(Data *o, T *actual)
787 {
788 if (d == o) return;
789 if (o)
790 o->weakref.ref();
791 if (d && !d->weakref.deref())
792 delete d;
793 d = o;
794 value = actual;
795 }
796
797 // ### TODO - QTBUG-88102: remove all users of this API; no one should ever
798 // access a weak pointer's data but the weak pointer itself
799 inline T *internalData() const noexcept
800 {
801 return d == nullptr || d->strongref.loadRelaxed() == 0 ? nullptr : value;
802 }
803
804 Data *d;
805 T *value;
806};
807
808namespace QtPrivate {
810 template <typename T>
811 static T *internalData(const QWeakPointer<T> &p) noexcept { return p.internalData(); }
812};
813// hack to delay name lookup to instantiation time by making
814// EnableInternalData a dependent name:
815template <typename T>
817}
818
819template <class T>
821{
822protected:
826
827public:
828 inline QSharedPointer<T> sharedFromThis() { return QSharedPointer<T>(weakPointer); }
829 inline QSharedPointer<const T> sharedFromThis() const { return QSharedPointer<const T>(weakPointer); }
830
831private:
832 template <class X> friend class QSharedPointer;
833 template <class X>
834 inline void initializeFromSharedPointer(const QSharedPointer<X> &ptr) const
835 {
836 weakPointer = ptr;
837 }
838
839 mutable QWeakPointer<T> weakPointer;
840};
841
842//
843// operator-
844//
845template <class T, class X>
847{
848 return ptr1.data() - ptr2.data();
849}
850template <class T, class X>
852{
853 return ptr1.data() - ptr2;
854}
855template <class T, class X>
857{
858 return ptr1 - ptr2.data();
859}
860
861//
862// qHash
863//
864template <class T>
865Q_INLINE_TEMPLATE size_t qHash(const QSharedPointer<T> &ptr, size_t seed = 0)
866{
867 return qHash(ptr.data(), seed);
868}
869
870
871template <class T>
872Q_INLINE_TEMPLATE QWeakPointer<T> QSharedPointer<T>::toWeakRef() const
873{
874 return QWeakPointer<T>(*this);
875}
876
877template <class T>
878inline void swap(QSharedPointer<T> &p1, QSharedPointer<T> &p2) noexcept
879{ p1.swap(p2); }
880
881template <class T>
882inline void swap(QWeakPointer<T> &p1, QWeakPointer<T> &p2) noexcept
883{ p1.swap(p2); }
884
885namespace QtSharedPointer {
886// helper functions:
887 template <class X, class T>
894
895 template <class X, class T>
897 {
899 result.d = std::exchange(src.d, nullptr);
901 src.value.reset(nullptr);
902 return result;
903 }
904}
905
906// cast operators
907template <class X, class T>
908Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &src)
909{
910 X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
911 return QtSharedPointer::copyAndSetPointer(ptr, src);
912}
913template <class X, class T>
914Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(QSharedPointer<T> &&src)
915{
916 X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
917 return QtSharedPointer::movePointer(ptr, 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}
924
925template <class X, class T>
926Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src)
927{
928 X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
929 if (!ptr)
930 return QSharedPointer<X>();
931 return QtSharedPointer::copyAndSetPointer(ptr, src);
932}
933template <class X, class T>
934Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(QSharedPointer<T> &&src)
935{
936 X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
937 if (!ptr)
938 return QSharedPointer<X>();
939 return QtSharedPointer::movePointer(ptr, std::move(src));
940}
941template <class X, class T>
942Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src)
943{
944 return qSharedPointerDynamicCast<X>(src.toStrongRef());
945}
946
947template <class X, class T>
948Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src)
949{
950 X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
951 return QtSharedPointer::copyAndSetPointer(ptr, src);
952}
953template <class X, class T>
954Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(QSharedPointer<T> &&src)
955{
956 X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
957 return QtSharedPointer::movePointer(ptr, std::move(src));
958}
959template <class X, class T>
960Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src)
961{
962 return qSharedPointerConstCast<X>(src.toStrongRef());
963}
964
965template <class X, class T>
966Q_INLINE_TEMPLATE
967QWeakPointer<X> qWeakPointerCast(const QSharedPointer<T> &src)
968{
969 return qSharedPointerCast<X>(src).toWeakRef();
970}
971
972#ifndef QT_NO_QOBJECT
973template <class X, class T>
974Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src)
975{
976 X *ptr = qobject_cast<X *>(src.data());
977 if (!ptr)
978 return QSharedPointer<X>();
979 return QtSharedPointer::copyAndSetPointer(ptr, src);
980}
981template <class X, class T>
982Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(QSharedPointer<T> &&src)
983{
984 X *ptr = qobject_cast<X *>(src.data());
985 if (!ptr)
986 return QSharedPointer<X>();
987 return QtSharedPointer::movePointer(ptr, std::move(src));
988}
989template <class X, class T>
990Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src)
991{
992 return qSharedPointerObjectCast<X>(src.toStrongRef());
993}
994
995template <class X, class T>
998{
999 return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type>(src);
1000}
1001template <class X, class T>
1004{
1005 return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type>(std::move(src));
1006}
1007template <class X, class T>
1010{
1011 return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type>(src);
1012}
1013
1014/// ### TODO - QTBUG-88102: make this use toStrongRef() (once support for
1015/// storing non-managed QObjects in QWeakPointer is removed)
1016template<typename T>
1017QWeakPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
1018qWeakPointerFromVariant(const QVariant &variant)
1019{
1020 return QWeakPointer<T>(qobject_cast<T*>(QtPrivate::EnableInternalData::internalData(QtSharedPointer::weakPointerFromVariant_internal(variant))));
1021}
1022template<typename T>
1023QSharedPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
1024qSharedPointerFromVariant(const QVariant &variant)
1025{
1026 return qSharedPointerObjectCast<T>(QtSharedPointer::sharedPointerFromVariant_internal(variant));
1027}
1028
1029// std::shared_ptr helpers
1030
1031template <typename X, class T>
1032std::shared_ptr<X> qobject_pointer_cast(const std::shared_ptr<T> &src)
1033{
1034 using element_type = typename std::shared_ptr<X>::element_type;
1035 if (auto ptr = qobject_cast<element_type *>(src.get()))
1036 return std::shared_ptr<X>(src, ptr);
1037 return std::shared_ptr<X>();
1038}
1039
1040template <typename X, class T>
1041std::shared_ptr<X> qobject_pointer_cast(std::shared_ptr<T> &&src)
1042{
1043 using element_type = typename std::shared_ptr<X>::element_type;
1044 auto castResult = qobject_cast<element_type *>(src.get());
1045 if (castResult) {
1046 // C++2a's move aliasing constructor will leave src empty.
1047 // Before C++2a we don't really know if the compiler has support for it.
1048 // The move aliasing constructor is the resolution for LWG2996,
1049 // which does not impose a feature-testing macro. So: clear src.
1050 return std::shared_ptr<X>(std::exchange(src, nullptr), castResult);
1051 }
1052 return std::shared_ptr<X>();
1053}
1054
1055template <typename X, class T>
1056std::shared_ptr<X> qSharedPointerObjectCast(const std::shared_ptr<T> &src)
1057{
1058 return qobject_pointer_cast<X>(src);
1059}
1060
1061template <typename X, class T>
1062std::shared_ptr<X> qSharedPointerObjectCast(std::shared_ptr<T> &&src)
1063{
1064 return qobject_pointer_cast<X>(std::move(src));
1065}
1066
1067#endif
1068
1071
1072
1073QT_END_NAMESPACE
1074
1075#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:431
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)
Q_DECLARE_TYPEINFO_BODY(QWeakPointer< T >, Q_RELOCATABLE_TYPE)
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)