Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
6#ifndef Q_QDOC
7
8#ifndef QSHAREDPOINTER_H
9#error Do not include qsharedpointer_impl.h directly
10#endif
11
12#if 0
13#pragma qt_sync_skip_header_check
14#pragma qt_sync_stop_processing
15#endif
16
17#if 0
18// These macros are duplicated here to make syncqt not complain a about
19// this header, as we have a "qt_sync_stop_processing" below, which in turn
20// is here because this file contains a template mess and duplicates the
21// classes found in qsharedpointer.h
24#pragma qt_sync_stop_processing
25#endif
26
27#include <new>
28#include <QtCore/qatomic.h>
29#include <QtCore/qhashfunctions.h>
30#include <QtCore/qmetatype.h> // for IsPointerToTypeDerivedFromQObject
31#include <QtCore/qxptype_traits.h>
32
33#include <memory>
34
36
37class QObject;
38template <class T>
39T qobject_cast(const QObject *object);
40
41//
42// forward declarations
43//
44template <class T> class QWeakPointer;
45template <class T> class QSharedPointer;
46template <class T> class QEnableSharedFromThis;
47
48class QVariant;
49
50template <class X, class T>
51QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &ptr);
52template <class X, class T>
53QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &ptr);
54template <class X, class T>
55QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &ptr);
56
57#ifndef QT_NO_QOBJECT
58template <class X, class T>
59QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &ptr);
60#endif
61
62namespace QtPrivate {
63struct EnableInternalData;
64}
65
66namespace QtSharedPointer {
67 template <class T> class ExternalRefCount;
68
69 template <class X, class Y> QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
70
71 // used in debug mode to verify the reuse of pointers
72 Q_CORE_EXPORT void internalSafetyCheckAdd(const void *, const volatile void *);
73 Q_CORE_EXPORT void internalSafetyCheckRemove(const void *);
74
75 template <class T, typename Klass, typename RetVal>
76 inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)())
77 { if (t) (t->*memberDeleter)(); }
78 template <class T, typename Deleter>
79 inline void executeDeleter(T *t, Deleter d)
80 { d(t); }
81 struct NormalDeleter {};
82
83 // this uses partial template specialization
84 template <class T> struct RemovePointer;
85 template <class T> struct RemovePointer<T *> { typedef T Type; };
86 template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; };
87 template <class T> struct RemovePointer<QWeakPointer<T> > { typedef T Type; };
88
89 // This class is the d-pointer of QSharedPointer and QWeakPointer.
90 //
91 // It is a reference-counted reference counter. "strongref" is the inner
92 // reference counter, and it tracks the lifetime of the pointer itself.
93 // "weakref" is the outer reference counter and it tracks the lifetime of
94 // the ExternalRefCountData object.
95 //
96 // The deleter is stored in the destroyer member and is always a pointer to
97 // a static function in ExternalRefCountWithCustomDeleter or in
98 // ExternalRefCountWithContiguousData
100 {
105
114
115 void destroy() { destroyer(this); }
116
117#ifndef QT_NO_QOBJECT
118 Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *);
120 Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable);
121 )
122 QT6_ONLY(Q_CORE_EXPORT void checkQObjectShared(const QObject *);)
123#endif
124 inline void checkQObjectShared(...) { }
125 inline void setQObjectShared(...) { }
126
127 // Normally, only subclasses of ExternalRefCountData are allocated
128 // One exception exists in getAndRef; that uses the global operator new
129 // to prevent a mismatch with the custom operator delete
130 inline void *operator new(std::size_t) = delete;
131 // placement new
132 inline void *operator new(std::size_t, void *ptr) noexcept { return ptr; }
133 inline void operator delete(void *ptr) { ::operator delete(ptr); }
134 inline void operator delete(void *, void *) { }
135 };
136 // sizeof(ExternalRefCountData) = 12 (32-bit) / 16 (64-bit)
137
138 template <class T, typename Deleter>
140 {
141 Deleter deleter;
142 T *ptr;
143
144 CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {}
146 };
147 // sizeof(CustomDeleter) = sizeof(Deleter) + sizeof(void*) + padding
148 // for Deleter = stateless functor: 8 (32-bit) / 16 (64-bit) due to padding
149 // for Deleter = function pointer: 8 (32-bit) / 16 (64-bit)
150 // for Deleter = PMF: 12 (32-bit) / 24 (64-bit) (GCC)
151
152 // This specialization of CustomDeleter for a deleter of type NormalDeleter
153 // is an optimization: instead of storing a pointer to a function that does
154 // the deleting, we simply delete the pointer ourselves.
155 template <class T>
157 {
158 T *ptr;
159
161 void execute() { delete ptr; }
162 };
163 // sizeof(CustomDeleter specialization) = sizeof(void*)
164
165 // This class extends ExternalRefCountData and implements
166 // the static function that deletes the object. The pointer and the
167 // custom deleter are kept in the "extra" member so we can construct
168 // and destruct it independently of the full structure.
169 template <class T, typename Deleter>
171 {
174 CustomDeleter<T, Deleter> extra;
175
176 static inline void deleter(ExternalRefCountData *self)
177 {
178 Self *realself = static_cast<Self *>(self);
179 realself->extra.execute();
180
181 // delete the deleter too
182 realself->extra.~CustomDeleter<T, Deleter>();
183 }
185 {
187 deleter(self);
188 }
189
190 static inline Self *create(T *ptr, Deleter userDeleter, DestroyerFn actualDeleter)
191 {
192 Self *d = static_cast<Self *>(::operator new(sizeof(Self)));
193
194 // initialize the two sub-objects
195 new (&d->extra) CustomDeleter<T, Deleter>(ptr, userDeleter);
196 new (d) BaseClass(actualDeleter); // can't throw
197
198 return d;
199 }
200 private:
201 // prevent construction
205 };
206
207 // This class extends ExternalRefCountData and adds a "T"
208 // member. That way, when the create() function is called, we allocate
209 // memory for both QSharedPointer's d-pointer and the actual object being
210 // tracked.
211 template <class T>
213 {
215 typedef typename std::remove_cv<T>::type NoCVType;
217
218 static void deleter(ExternalRefCountData *self)
219 {
221 static_cast<ExternalRefCountWithContiguousData *>(self);
222 that->data.~T();
223 Q_UNUSED(that); // MSVC warns if T has a trivial destructor
224 }
226 {
228 deleter(self);
229 }
231
233 {
235 static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData)));
236
237 // initialize the d-pointer sub-object
238 // leave d->data uninitialized
239 new (d) Parent(destroy); // can't throw
240
241 *ptr = &d->data;
242 return d;
243 }
244
245 private:
246 // prevent construction
250 };
251
252#ifndef QT_NO_QOBJECT
253 Q_CORE_EXPORT QWeakPointer<QObject> weakPointerFromVariant_internal(const QVariant &variant);
254 Q_CORE_EXPORT QSharedPointer<QObject> sharedPointerFromVariant_internal(const QVariant &variant);
255#endif
256} // namespace QtSharedPointer
257
258template <class T> class QSharedPointer
259{
261 template <typename X>
262 using IfCompatible = typename std::enable_if<std::is_convertible<X*, T*>::value, bool>::type;
263
264public:
265 typedef T Type;
266 typedef T element_type;
267 typedef T value_type;
269 typedef const value_type *const_pointer;
273
274 T *data() const noexcept { return value; }
275 T *get() const noexcept { return value; }
276 bool isNull() const noexcept { return !data(); }
277 explicit operator bool() const noexcept { return !isNull(); }
278 bool operator !() const noexcept { return isNull(); }
279 T &operator*() const { return *data(); }
280 T *operator->() const noexcept { return data(); }
281
283 constexpr QSharedPointer() noexcept : value(nullptr), d(nullptr) { }
284 ~QSharedPointer() { deref(); }
285
287 constexpr QSharedPointer(std::nullptr_t) noexcept : value(nullptr), d(nullptr) { }
288
289 template <class X, IfCompatible<X> = true>
291 inline explicit QSharedPointer(X *ptr) : value(ptr) // noexcept
292 { internalConstruct(ptr, QtSharedPointer::NormalDeleter()); }
293
294 template <class X, typename Deleter, IfCompatible<X> = true>
296 inline QSharedPointer(X *ptr, Deleter deleter) : value(ptr) // throws
297 { internalConstruct(ptr, deleter); }
298
299 template <typename Deleter>
301 QSharedPointer(std::nullptr_t, Deleter deleter) : value(nullptr)
302 { internalConstruct(static_cast<T *>(nullptr), deleter); }
303
305 QSharedPointer(const QSharedPointer &other) noexcept : value(other.value), d(other.d)
306 { if (d) ref(); }
308 {
310 swap(copy);
311 return *this;
312 }
315 : value(other.value), d(other.d)
316 {
317 other.d = nullptr;
318 other.value = nullptr;
319 }
320 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSharedPointer)
321
322 template <class X, IfCompatible<X> = true>
324 QSharedPointer(QSharedPointer<X> &&other) noexcept
325 : value(other.value), d(other.d)
326 {
327 other.d = nullptr;
328 other.value = nullptr;
329 }
330
331 template <class X, IfCompatible<X> = true>
332 QSharedPointer &operator=(QSharedPointer<X> &&other) noexcept
333 {
334 QSharedPointer moved(std::move(other));
335 swap(moved);
336 return *this;
337 }
338
339 template <class X, IfCompatible<X> = true>
341 QSharedPointer(const QSharedPointer<X> &other) noexcept : value(other.value), d(other.d)
342 { if (d) ref(); }
343
344 template <class X, IfCompatible<X> = true>
345 inline QSharedPointer &operator=(const QSharedPointer<X> &other)
346 {
348 swap(copy);
349 return *this;
350 }
351
352 template <class X, IfCompatible<X> = true>
354 inline QSharedPointer(const QWeakPointer<X> &other) : value(nullptr), d(nullptr)
355 { *this = other; }
356
357 template <class X, IfCompatible<X> = true>
358 inline QSharedPointer<T> &operator=(const QWeakPointer<X> &other)
359 { internalSet(other.d, other.value); return *this; }
360
361 inline void swap(QSharedPointer &other) noexcept
362 { this->internalSwap(other); }
363
364 inline void reset() { clear(); }
365 inline void reset(T *t)
367 template <typename Deleter>
368 inline void reset(T *t, Deleter deleter)
369 { QSharedPointer copy(t, deleter); swap(copy); }
370
371 template <class X>
372 QSharedPointer<X> staticCast() const
373 {
374 return qSharedPointerCast<X, T>(*this);
375 }
376
377 template <class X>
378 QSharedPointer<X> dynamicCast() const
379 {
380 return qSharedPointerDynamicCast<X, T>(*this);
381 }
382
383 template <class X>
384 QSharedPointer<X> constCast() const
385 {
386 return qSharedPointerConstCast<X, T>(*this);
387 }
388
389#ifndef QT_NO_QOBJECT
390 template <class X>
391 QSharedPointer<X> objectCast() const
392 {
393 return qSharedPointerObjectCast<X, T>(*this);
394 }
395#endif
396
397 inline void clear() { QSharedPointer copy; swap(copy); }
398
399 [[nodiscard]] QWeakPointer<T> toWeakRef() const;
400
401 template <typename... Args>
402 [[nodiscard]] static QSharedPointer create(Args && ...arguments)
403 {
405# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
406 typename Private::DestroyerFn destroy = &Private::safetyCheckDeleter;
407# else
408 typename Private::DestroyerFn destroy = &Private::deleter;
409# endif
410 typename Private::DestroyerFn noDestroy = &Private::noDeleter;
412 typename std::remove_cv<T>::type *ptr;
413 result.d = Private::create(&ptr, noDestroy);
414
415 // now initialize the data
416 new (ptr) T(std::forward<Args>(arguments)...);
417 result.value = ptr;
418 result.d->destroyer = destroy;
419 result.d->setQObjectShared(result.value, true);
420# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
421 internalSafetyCheckAdd(result.d, result.value);
422# endif
423 result.enableSharedFromThis(result.data());
424 return result;
425 }
426
427#define DECLARE_COMPARE_SET(T1, A1, T2, A2) \
428 friend bool operator==(T1, T2) noexcept \
429 { return A1 == A2; } \
430 friend bool operator!=(T1, T2) noexcept \
431 { return A1 != A2; }
432
433#define DECLARE_TEMPLATE_COMPARE_SET(T1, A1, T2, A2) \
434 template <typename X> \
435 friend bool operator==(T1, T2) noexcept \
436 { return A1 == A2; } \
437 template <typename X> \
438 friend bool operator!=(T1, T2) noexcept \
439 { return A1 != A2; }
440
441 DECLARE_TEMPLATE_COMPARE_SET(const QSharedPointer &p1, p1.data(), const QSharedPointer<X> &p2, p2.data())
444 DECLARE_COMPARE_SET(const QSharedPointer &p1, p1.data(), std::nullptr_t, nullptr)
445 DECLARE_COMPARE_SET(std::nullptr_t, nullptr, const QSharedPointer &p2, p2.data())
446#undef DECLARE_TEMPLATE_COMPARE_SET
447#undef DECLARE_COMPARE_SET
448
449 template <typename X>
450 bool owner_before(const QSharedPointer<X> &other) const noexcept
451 { return std::less<>()(d, other.d); }
452 template <typename X>
453 bool owner_before(const QWeakPointer<X> &other) const noexcept
454 { return std::less<>()(d, other.d); }
455
456 template <typename X>
457 bool owner_equal(const QSharedPointer<X> &other) const noexcept
458 { return d == other.d; }
459 template <typename X>
460 bool owner_equal(const QWeakPointer<X> &other) const noexcept
461 { return d == other.d; }
462
463 size_t owner_hash() const noexcept
464 { return std::hash<Data *>()(d); }
465
466private:
469
470 void deref() noexcept
471 { deref(d); }
472 static void deref(Data *dd) noexcept
473 {
474 if (!dd) return;
475 if (!dd->strongref.deref()) {
476 dd->destroy();
477 }
478 if (!dd->weakref.deref())
479 delete dd;
480 }
481
482 template <class X>
483 inline void enableSharedFromThis(const QEnableSharedFromThis<X> *ptr)
484 {
485 ptr->initializeFromSharedPointer(constCast<typename std::remove_cv<T>::type>());
486 }
487
488 inline void enableSharedFromThis(...) {}
489
490 template <typename X, typename Deleter>
491 inline void internalConstruct(X *ptr, Deleter deleter)
492 {
494# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
495 typename Private::DestroyerFn actualDeleter = &Private::safetyCheckDeleter;
496# else
497 typename Private::DestroyerFn actualDeleter = &Private::deleter;
498# endif
499 d = Private::create(ptr, deleter, actualDeleter);
500
501#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
503#endif
504 enableSharedFromThis(ptr);
505 }
506
507 void internalSwap(QSharedPointer &other) noexcept
508 {
509 qt_ptr_swap(d, other.d);
510 qt_ptr_swap(this->value, other.value);
511 }
512
513 template <class X> friend class QSharedPointer;
514 template <class X> friend class QWeakPointer;
515 template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
516 void ref() const noexcept { d->weakref.ref(); d->strongref.ref(); }
517
518 inline void internalSet(Data *o, T *actual)
519 {
520 if (o) {
521 // increase the strongref, but never up from zero
522 // or less (-1 is used by QWeakPointer on untracked QObject)
523 int tmp = o->strongref.loadRelaxed();
524 while (tmp > 0) {
525 // try to increment from "tmp" to "tmp + 1"
526 if (o->strongref.testAndSetRelaxed(tmp, tmp + 1))
527 break; // succeeded
528 tmp = o->strongref.loadRelaxed(); // failed, try again
529 }
530
531 if (tmp > 0)
532 o->weakref.ref();
533 else
534 o = nullptr;
535 }
536
537 qt_ptr_swap(d, o);
538 qt_ptr_swap(this->value, actual);
539 if (!d || d->strongref.loadRelaxed() == 0)
540 this->value = nullptr;
541
542 // dereference saved data
543 deref(o);
544 }
545
546 Type *value;
547 Data *d;
548};
549
550template <class T>
552{
554 template <typename X>
555 using IfCompatible = typename std::enable_if<std::is_convertible<X*, T*>::value, bool>::type;
556
557 template <typename X>
558 using IfVirtualBase = typename std::enable_if<qxp::is_virtual_base_of_v<T, X>, bool>::type;
559
560 template <typename X>
561 using IfNotVirtualBase = typename std::enable_if<!qxp::is_virtual_base_of_v<T, X>, bool>::type;
562
563public:
564 typedef T element_type;
565 typedef T value_type;
567 typedef const value_type *const_pointer;
571
572 bool isNull() const noexcept { return d == nullptr || d->strongref.loadRelaxed() == 0 || value == nullptr; }
573 explicit operator bool() const noexcept { return !isNull(); }
574 bool operator !() const noexcept { return isNull(); }
575
577 constexpr QWeakPointer() noexcept : d(nullptr), value(nullptr) { }
578 inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
579
581 QWeakPointer(const QWeakPointer &other) noexcept : d(other.d), value(other.value)
582 { if (d) d->weakref.ref(); }
585 : d(other.d), value(other.value)
586 {
587 other.d = nullptr;
588 other.value = nullptr;
589 }
590 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QWeakPointer)
591
592 template <class X, IfCompatible<X> = true, IfNotVirtualBase<X> = true>
594 QWeakPointer(QWeakPointer<X> &&other) noexcept
595 : d(std::exchange(other.d, nullptr)),
596 value(std::exchange(other.value, nullptr))
597 {
598 }
599
600 template <class X, IfCompatible<X> = true, IfVirtualBase<X> = true>
602 QWeakPointer(QWeakPointer<X> &&other) noexcept
603 : d(other.d), value(other.toStrongRef().get()) // must go through QSharedPointer, see below
604 {
605 other.d = nullptr;
606 other.value = nullptr;
607 }
608
609 template <class X, IfCompatible<X> = true>
610 QWeakPointer &operator=(QWeakPointer<X> &&other) noexcept
611 {
612 QWeakPointer moved(std::move(other));
613 swap(moved);
614 return *this;
615 }
616
618 {
620 swap(copy);
621 return *this;
622 }
623
624 void swap(QWeakPointer &other) noexcept
625 {
626 qt_ptr_swap(this->d, other.d);
627 qt_ptr_swap(this->value, other.value);
628 }
629
631 inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data())
632 { if (d) d->weakref.ref();}
633 inline QWeakPointer &operator=(const QSharedPointer<T> &o)
634 {
635 internalSet(o.d, o.value);
636 return *this;
637 }
638
639 template <class X, IfCompatible<X> = true>
641 inline QWeakPointer(const QWeakPointer<X> &o) : d(nullptr), value(nullptr)
642 { *this = o; }
643
644 template <class X, IfCompatible<X> = true>
645 inline QWeakPointer &operator=(const QWeakPointer<X> &o)
646 {
647 // conversion between X and T could require access to the virtual table
648 // so force the operation to go through QSharedPointer
649 *this = o.toStrongRef();
650 return *this;
651 }
652
653 template <class X, IfCompatible<X> = true>
655 inline QWeakPointer(const QSharedPointer<X> &o) : d(nullptr), value(nullptr)
656 { *this = o; }
657
658 template <class X, IfCompatible<X> = true>
659 inline QWeakPointer &operator=(const QSharedPointer<X> &o)
660 {
661 internalSet(o.d, o.data());
662 return *this;
663 }
664
665 inline void clear() { *this = QWeakPointer(); }
666
667 [[nodiscard]] QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
668 // std::weak_ptr compatibility:
669 [[nodiscard]] QSharedPointer<T> lock() const { return toStrongRef(); }
670
671 template <class X>
672 bool operator==(const QWeakPointer<X> &o) const noexcept
673 { return d == o.d && value == static_cast<const T *>(o.value); }
674
675 template <class X>
676 bool operator!=(const QWeakPointer<X> &o) const noexcept
677 { return !(*this == o); }
678
679 template <class X>
680 bool operator==(const QSharedPointer<X> &o) const noexcept
681 { return d == o.d; }
682
683 template <class X>
684 bool operator!=(const QSharedPointer<X> &o) const noexcept
685 { return !(*this == o); }
686
687 template <typename X>
688 friend bool operator==(const QSharedPointer<X> &p1, const QWeakPointer &p2) noexcept
689 { return p2 == p1; }
690 template <typename X>
691 friend bool operator!=(const QSharedPointer<X> &p1, const QWeakPointer &p2) noexcept
692 { return p2 != p1; }
693
694 friend bool operator==(const QWeakPointer &p, std::nullptr_t)
695 { return p.isNull(); }
696 friend bool operator==(std::nullptr_t, const QWeakPointer &p)
697 { return p.isNull(); }
698 friend bool operator!=(const QWeakPointer &p, std::nullptr_t)
699 { return !p.isNull(); }
700 friend bool operator!=(std::nullptr_t, const QWeakPointer &p)
701 { return !p.isNull(); }
702
703 template <typename X>
704 bool owner_before(const QWeakPointer<X> &other) const noexcept
705 { return std::less<>()(d, other.d); }
706 template <typename X>
707 bool owner_before(const QSharedPointer<X> &other) const noexcept
708 { return std::less<>()(d, other.d); }
709
710 template <typename X>
711 bool owner_equal(const QWeakPointer<X> &other) const noexcept
712 { return d == other.d; }
713 template <typename X>
714 bool owner_equal(const QSharedPointer<X> &other) const noexcept
715 { return d == other.d; }
716
717 size_t owner_hash() const noexcept
718 { return std::hash<Data *>()(d); }
719
720private:
722 template <class X> friend class QSharedPointer;
723 template <class X> friend class QWeakPointer;
724 template <class X> friend class QPointer;
725
726 template <class X>
727 inline QWeakPointer &assign(X *ptr)
728 { return *this = QWeakPointer<T>(ptr, true); }
729
730#ifndef QT_NO_QOBJECT
731 template <class X, IfCompatible<X> = true>
733 inline QWeakPointer(X *ptr, bool) : d(ptr ? Data::getAndRef(ptr) : nullptr), value(ptr)
734 { }
735#endif
736
737 inline void internalSet(Data *o, T *actual)
738 {
739 if (d == o) return;
740 if (o)
741 o->weakref.ref();
742 if (d && !d->weakref.deref())
743 delete d;
744 d = o;
745 value = actual;
746 }
747
748 // ### TODO - QTBUG-88102: remove all users of this API; no one should ever
749 // access a weak pointer's data but the weak pointer itself
750 inline T *internalData() const noexcept
751 {
752 return d == nullptr || d->strongref.loadRelaxed() == 0 ? nullptr : value;
753 }
754
755 Data *d;
756 T *value;
757};
758
759namespace QtPrivate {
761 template <typename T>
762 static T *internalData(const QWeakPointer<T> &p) noexcept { return p.internalData(); }
763};
764// hack to delay name lookup to instantiation time by making
765// EnableInternalData a dependent name:
766template <typename T>
768}
769
770template <class T>
772{
773protected:
777
778public:
779 inline QSharedPointer<T> sharedFromThis() { return QSharedPointer<T>(weakPointer); }
780 inline QSharedPointer<const T> sharedFromThis() const { return QSharedPointer<const T>(weakPointer); }
781
782private:
783 template <class X> friend class QSharedPointer;
784 template <class X>
785 inline void initializeFromSharedPointer(const QSharedPointer<X> &ptr) const
786 {
787 weakPointer = ptr;
788 }
789
790 mutable QWeakPointer<T> weakPointer;
791};
792
793//
794// operator-
795//
796template <class T, class X>
797Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
798{
799 return ptr1.data() - ptr2.data();
800}
801template <class T, class X>
802Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, X *ptr2)
803{
804 return ptr1.data() - ptr2;
805}
806template <class T, class X>
807Q_INLINE_TEMPLATE typename QSharedPointer<X>::difference_type operator-(T *ptr1, const QSharedPointer<X> &ptr2)
808{
809 return ptr1 - ptr2.data();
810}
811
812//
813// operator<
814//
815template <class T, class X>
816Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
817{
818 using CT = typename std::common_type<T *, X *>::type;
819 return std::less<CT>()(ptr1.data(), ptr2.data());
820}
821template <class T, class X>
822Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, X *ptr2)
823{
824 using CT = typename std::common_type<T *, X *>::type;
825 return std::less<CT>()(ptr1.data(), ptr2);
826}
827template <class T, class X>
828Q_INLINE_TEMPLATE bool operator<(T *ptr1, const QSharedPointer<X> &ptr2)
829{
830 using CT = typename std::common_type<T *, X *>::type;
831 return std::less<CT>()(ptr1, ptr2.data());
832}
833
834//
835// qHash
836//
837template <class T>
838Q_INLINE_TEMPLATE size_t qHash(const QSharedPointer<T> &ptr, size_t seed = 0)
839{
840 return qHash(ptr.data(), seed);
841}
842
843
844template <class T>
845Q_INLINE_TEMPLATE QWeakPointer<T> QSharedPointer<T>::toWeakRef() const
846{
847 return QWeakPointer<T>(*this);
848}
849
850template <class T>
851inline void swap(QSharedPointer<T> &p1, QSharedPointer<T> &p2) noexcept
852{ p1.swap(p2); }
853
854template <class T>
855inline void swap(QWeakPointer<T> &p1, QWeakPointer<T> &p2) noexcept
856{ p1.swap(p2); }
857
858namespace QtSharedPointer {
859// helper functions:
860 template <class X, class T>
861 Q_INLINE_TEMPLATE QSharedPointer<X> copyAndSetPointer(X *ptr, const QSharedPointer<T> &src)
862 {
863 QSharedPointer<X> result;
864 result.internalSet(src.d, ptr);
865 return result;
866 }
867}
868
869// cast operators
870template <class X, class T>
871Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &src)
872{
873 X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
875}
876template <class X, class T>
877Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &src)
878{
879 return qSharedPointerCast<X, T>(src.toStrongRef());
880}
881
882template <class X, class T>
883Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src)
884{
885 X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
886 if (!ptr)
887 return QSharedPointer<X>();
889}
890template <class X, class T>
891Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src)
892{
893 return qSharedPointerDynamicCast<X, T>(src.toStrongRef());
894}
895
896template <class X, class T>
897Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src)
898{
899 X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
901}
902template <class X, class T>
903Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src)
904{
905 return qSharedPointerConstCast<X, T>(src.toStrongRef());
906}
907
908template <class X, class T>
909Q_INLINE_TEMPLATE
910QWeakPointer<X> qWeakPointerCast(const QSharedPointer<T> &src)
911{
912 return qSharedPointerCast<X, T>(src).toWeakRef();
913}
914
915#ifndef QT_NO_QOBJECT
916template <class X, class T>
917Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src)
918{
919 X *ptr = qobject_cast<X *>(src.data());
921}
922template <class X, class T>
923Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src)
924{
925 return qSharedPointerObjectCast<X>(src.toStrongRef());
926}
927
928template <class X, class T>
929inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
930qobject_cast(const QSharedPointer<T> &src)
931{
932 return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
933}
934template <class X, class T>
935inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
936qobject_cast(const QWeakPointer<T> &src)
937{
938 return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
939}
940
943template<typename T>
944QWeakPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
949template<typename T>
950QSharedPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
955
956// std::shared_ptr helpers
957
958template <typename X, class T>
959std::shared_ptr<X> qobject_pointer_cast(const std::shared_ptr<T> &src)
960{
961 using element_type = typename std::shared_ptr<X>::element_type;
962 return std::shared_ptr<X>(src, qobject_cast<element_type *>(src.get()));
963}
964
965template <typename X, class T>
966std::shared_ptr<X> qobject_pointer_cast(std::shared_ptr<T> &&src)
967{
968 using element_type = typename std::shared_ptr<X>::element_type;
969 auto castResult = qobject_cast<element_type *>(src.get());
970 if (castResult) {
971 // C++2a's move aliasing constructor will leave src empty.
972 // Before C++2a we don't really know if the compiler has support for it.
973 // The move aliasing constructor is the resolution for LWG2996,
974 // which does not impose a feature-testing macro. So: clear src.
975 return std::shared_ptr<X>(std::exchange(src, nullptr), castResult);
976 }
977 return std::shared_ptr<X>();
978}
979
980template <typename X, class T>
981std::shared_ptr<X> qSharedPointerObjectCast(const std::shared_ptr<T> &src)
982{
983 return qobject_pointer_cast<X>(src);
984}
985
986template <typename X, class T>
987std::shared_ptr<X> qSharedPointerObjectCast(std::shared_ptr<T> &&src)
988{
989 return qobject_pointer_cast<X>(std::move(src));
990}
991
992#endif
993
994template<typename T> Q_DECLARE_TYPEINFO_BODY(QWeakPointer<T>, Q_RELOCATABLE_TYPE);
995template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedPointer<T>, Q_RELOCATABLE_TYPE);
996
997
999
1000#endif
bool ref() noexcept
bool deref() noexcept
void storeRelaxed(T newValue) noexcept
T loadRelaxed() const noexcept
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
Definition qobject.h:103
void swap(QPixmap &other) noexcept
Swaps pixmap other with this pixmap.
Definition qpixmap.h:43
\inmodule QtCore
Q_NODISCARD_CTOR QSharedPointer(X *ptr)
Creates a QSharedPointer that points to ptr.
Q_NODISCARD_CTOR QSharedPointer(X *ptr, Deleter deleter)
Creates a QSharedPointer that points to ptr.
bool owner_equal(const QSharedPointer< X > &other) const noexcept
bool isNull() const noexcept
Returns true if this object refers to \nullptr.
Q_NODISCARD_CTOR QSharedPointer(const QSharedPointer &other) noexcept
Creates a QSharedPointer object that shares other's pointer.
QSharedPointer & operator=(QSharedPointer< X > &&other) noexcept
Move-assigns other to this QSharedPointer instance.
QSharedPointer< X > constCast() const
Performs a \tt const_cast from this pointer's type to \tt X and returns a QSharedPointer that shares ...
bool operator!() const noexcept
Returns true if this object refers to \nullptr.
friend class QSharedPointer
Creates a QSharedPointer that is null (the object is holding a reference to \nullptr).
QWeakPointer< T > toWeakRef() const
Returns a weak reference object that shares the pointer referenced by this object.
QSharedPointer< X > objectCast() const
DECLARE_TEMPLATE_COMPARE_SET(const QSharedPointer &p1, p1.data(), const QSharedPointer< X > &p2, p2.data()) template< typename X > bool owner_before(const QSharedPointer< X > &other) const noexcept
QSharedPointer< T > & operator=(const QWeakPointer< X > &other)
Q_NODISCARD_CTOR QSharedPointer(const QSharedPointer< X > &other) noexcept
T * data() const noexcept
Returns the value of the pointer referenced by this object.
void reset(T *t, Deleter deleter)
QSharedPointer< X > dynamicCast() const
Performs a dynamic cast from this pointer's type to \tt X and returns a QSharedPointer that shares th...
~QSharedPointer()
Destroys this QSharedPointer object.
Q_NODISCARD_CTOR QSharedPointer(QSharedPointer &&other) noexcept
Move-constructs a QSharedPointer instance, making it point at the same object that other was pointing...
const value_type & const_reference
size_t owner_hash() const noexcept
bool owner_before(const QWeakPointer< X > &other) const noexcept
Q_NODISCARD_CTOR QSharedPointer(std::nullptr_t, Deleter deleter)
T * get() const noexcept
Q_NODISCARD_CTOR QSharedPointer(const QWeakPointer< X > &other)
const value_type * const_pointer
Q_NODISCARD_CTOR constexpr QSharedPointer(std::nullptr_t) noexcept
static QSharedPointer create(Args &&...arguments)
This is an overloaded member function, provided for convenience. It differs from the above function o...
T & operator*() const
Provides access to the shared pointer's members.
QSharedPointer & operator=(const QSharedPointer &other) noexcept
Makes this object share other's pointer.
QSharedPointer< X > staticCast() const
Performs a static cast from this pointer's type to \tt X and returns a QSharedPointer that shares the...
bool owner_equal(const QWeakPointer< X > &other) const noexcept
T * operator->() const noexcept
Provides access to the shared pointer's members.
Q_NODISCARD_CTOR QSharedPointer(QSharedPointer< X > &&other) noexcept
Move-constructs a QSharedPointer instance, making it point at the same object that other was pointing...
void swap(QSharedPointer &other) noexcept
QSharedPointer & operator=(const QSharedPointer< X > &other)
void clear()
Clears this QSharedPointer object, dropping the reference that it may have had to the pointer.
Q_NODISCARD_CTOR constexpr QSharedPointer() noexcept
\inmodule QtCore
Definition qvariant.h:65
\inmodule QtCore
friend bool operator==(const QWeakPointer &p, std::nullptr_t)
size_t owner_hash() const noexcept
const value_type & const_reference
friend bool operator!=(const QWeakPointer &p, std::nullptr_t)
Q_NODISCARD_CTOR QWeakPointer(QWeakPointer &&other) noexcept
bool owner_before(const QSharedPointer< X > &other) const noexcept
Q_NODISCARD_CTOR QWeakPointer(const QWeakPointer &other) noexcept
Creates a QWeakPointer that holds a weak reference to the pointer referenced by other.
QWeakPointer & operator=(QWeakPointer< X > &&other) noexcept
friend bool operator==(const QSharedPointer< X > &p1, const QWeakPointer &p2) noexcept
QWeakPointer & operator=(const QSharedPointer< X > &o)
QWeakPointer & operator=(const QWeakPointer &other) noexcept
Makes this object share other's pointer.
friend bool operator==(std::nullptr_t, const QWeakPointer &p)
friend bool operator!=(const QSharedPointer< X > &p1, const QWeakPointer &p2) noexcept
bool operator==(const QSharedPointer< X > &o) const noexcept
bool owner_before(const QWeakPointer< X > &other) const noexcept
void clear()
Clears this QWeakPointer object, dropping the reference that it may have had to the pointer.
QSharedPointer< T > toStrongRef() const
Promotes this weak reference to a strong one and returns a QSharedPointer object holding that referen...
QWeakPointer & operator=(const QSharedPointer< T > &o)
Makes this object share other's pointer.
bool operator!() const noexcept
Returns true if this object refers to \nullptr.
bool operator==(const QWeakPointer< X > &o) const noexcept
bool owner_equal(const QWeakPointer< X > &other) const noexcept
Q_NODISCARD_CTOR constexpr QWeakPointer() noexcept
QWeakPointer & operator=(const QWeakPointer< X > &o)
QSharedPointer< T > lock() const
bool operator!=(const QWeakPointer< X > &o) const noexcept
const value_type * const_pointer
Q_NODISCARD_CTOR QWeakPointer(const QWeakPointer< X > &o)
bool isNull() const noexcept
Returns true if this object refers to \nullptr.
friend class QWeakPointer
Creates a QWeakPointer that points to nothing.
Q_NODISCARD_CTOR QWeakPointer(QWeakPointer< X > &&other) noexcept
~QWeakPointer()
Destroys this QWeakPointer object.
bool operator!=(const QSharedPointer< X > &o) const noexcept
friend bool operator!=(std::nullptr_t, const QWeakPointer &p)
value_type * pointer
bool owner_equal(const QSharedPointer< X > &other) const noexcept
Q_NODISCARD_CTOR QWeakPointer(const QSharedPointer< T > &o)
Creates a QWeakPointer that holds a weak reference to the pointer referenced by other.
value_type & reference
Q_NODISCARD_CTOR QWeakPointer(const QSharedPointer< X > &o)
void swap(QWeakPointer &other) noexcept
QPixmap p2
QPixmap p1
[0]
QList< QVariant > arguments
Combined button and popup list for selecting options.
\macro QT_NO_KEYWORDS >
QSharedPointer< X > copyAndSetPointer(X *ptr, const QSharedPointer< Y > &src)
Q_CORE_EXPORT QWeakPointer< QObject > weakPointerFromVariant_internal(const QVariant &variant)
Q_CORE_EXPORT void internalSafetyCheckRemove(const void *)
void executeDeleter(T *t, RetVal(Klass::*memberDeleter)())
Q_CORE_EXPORT void internalSafetyCheckAdd(const void *, const volatile void *)
Q_CORE_EXPORT QSharedPointer< QObject > sharedPointerFromVariant_internal(const QVariant &variant)
constexpr Initialization Uninitialized
Initialization
static jboolean copy(JNIEnv *, jobject)
#define Q_NODISCARD_CTOR
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static ControlElement< T > * ptr(QWidget *widget)
T qobject_cast(QObject *object)
\variable QObject::staticMetaObject
Definition qobject.h:419
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum src
GLenum type
GLboolean enable
GLint ref
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
Definition qrandom.cpp:196
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
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 > qSharedPointerCast(const QSharedPointer< T > &ptr)
QWeakPointer< typename std::enable_if< QtPrivate::IsPointerToTypeDerivedFromQObject< T * >::Value, T >::type > qWeakPointerFromVariant(const QVariant &variant)
Q_INLINE_TEMPLATE size_t qHash(const QSharedPointer< T > &ptr, size_t seed=0)
#define DECLARE_TEMPLATE_COMPARE_SET(T1, A1, T2, A2)
QSharedPointer< X > qSharedPointerDynamicCast(const QSharedPointer< T > &ptr)
Q_INLINE_TEMPLATE bool operator<(const QSharedPointer< T > &ptr1, const QSharedPointer< X > &ptr2)
std::shared_ptr< X > qobject_pointer_cast(const std::shared_ptr< T > &src)
T qobject_cast(const QObject *object)
Definition qobject.h:430
QSharedPointer< typename std::enable_if< QtPrivate::IsPointerToTypeDerivedFromQObject< T * >::Value, T >::type > qSharedPointerFromVariant(const QVariant &variant)
#define DECLARE_COMPARE_SET(T1, A1, T2, A2)
QSharedPointer< X > qSharedPointerObjectCast(const QSharedPointer< T > &ptr)
Q_INLINE_TEMPLATE QWeakPointer< X > qWeakPointerCast(const QSharedPointer< T > &src)
constexpr void qt_ptr_swap(T *&lhs, T *&rhs) noexcept
Definition qswap.h:29
#define Q_UNUSED(x)
@ Q_RELOCATABLE_TYPE
Definition qtypeinfo.h:158
#define Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS)
Definition qtypeinfo.h:163
ptrdiff_t qptrdiff
Definition qtypes.h:164
QObject::connect nullptr
QVariant variant
[1]
QSharedPointer< T > other(t)
[5]
this swap(other)
static T * internalData(const QWeakPointer< T > &p) noexcept
void(* DestroyerFn)(ExternalRefCountData *)
QT6_ONLY(Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable);) inline void checkQObjectShared(...)
static Q_CORE_EXPORT ExternalRefCountData * getAndRef(const QObject *)
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)
Definition moc.h:23