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
22QT_BEGIN_NAMESPACE
23QT_END_NAMESPACE
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
35QT_BEGIN_NAMESPACE
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
99 struct ExternalRefCountData
100 {
101 typedef void (*DestroyerFn)(ExternalRefCountData *);
102 QBasicAtomicInt weakref;
103 QBasicAtomicInt strongref;
104 DestroyerFn destroyer;
105
106 inline ExternalRefCountData(DestroyerFn d)
107 : destroyer(d)
108 {
109 strongref.storeRelaxed(newValue: 1);
110 weakref.storeRelaxed(newValue: 1);
111 }
112 inline ExternalRefCountData(Qt::Initialization) { }
113 ~ExternalRefCountData() { Q_ASSERT(!weakref.loadRelaxed()); Q_ASSERT(strongref.loadRelaxed() <= 0); }
114
115 void destroy() { destroyer(this); }
116
117#ifndef QT_NO_QOBJECT
118 Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *);
119 QT6_ONLY(
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>
139 struct CustomDeleter
140 {
141 Deleter deleter;
142 T *ptr;
143
144 CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {}
145 void execute() { executeDeleter(ptr, deleter); }
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>
156 struct CustomDeleter<T, NormalDeleter>
157 {
158 T *ptr;
159
160 CustomDeleter(T *p, NormalDeleter) : ptr(p) {}
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>
170 struct ExternalRefCountWithCustomDeleter: public ExternalRefCountData
171 {
172 typedef ExternalRefCountWithCustomDeleter Self;
173 typedef ExternalRefCountData BaseClass;
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 }
184 static void safetyCheckDeleter(ExternalRefCountData *self)
185 {
186 internalSafetyCheckRemove(self);
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
202 ExternalRefCountWithCustomDeleter() = delete;
203 ~ExternalRefCountWithCustomDeleter() = delete;
204 Q_DISABLE_COPY(ExternalRefCountWithCustomDeleter)
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>
212 struct ExternalRefCountWithContiguousData: public ExternalRefCountData
213 {
214 typedef ExternalRefCountData Parent;
215 typedef typename std::remove_cv<T>::type NoCVType;
216 NoCVType data;
217
218 static void deleter(ExternalRefCountData *self)
219 {
220 ExternalRefCountWithContiguousData *that =
221 static_cast<ExternalRefCountWithContiguousData *>(self);
222 that->data.~T();
223 Q_UNUSED(that); // MSVC warns if T has a trivial destructor
224 }
225 static void safetyCheckDeleter(ExternalRefCountData *self)
226 {
227 internalSafetyCheckRemove(self);
228 deleter(self);
229 }
230 static void noDeleter(ExternalRefCountData *) { }
231
232 static inline ExternalRefCountData *create(NoCVType **ptr, DestroyerFn destroy)
233 {
234 ExternalRefCountWithContiguousData *d =
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
247 ExternalRefCountWithContiguousData() = delete;
248 ~ExternalRefCountWithContiguousData() = delete;
249 Q_DISABLE_COPY(ExternalRefCountWithContiguousData)
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{
260 typedef QtSharedPointer::ExternalRefCountData Data;
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;
268 typedef value_type *pointer;
269 typedef const value_type *const_pointer;
270 typedef value_type &reference;
271 typedef const value_type &const_reference;
272 typedef qptrdiff difference_type;
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
282 Q_NODISCARD_CTOR
283 constexpr QSharedPointer() noexcept : value(nullptr), d(nullptr) { }
284 ~QSharedPointer() { deref(); }
285
286 Q_NODISCARD_CTOR
287 constexpr QSharedPointer(std::nullptr_t) noexcept : value(nullptr), d(nullptr) { }
288
289 template <class X, IfCompatible<X> = true>
290 Q_NODISCARD_CTOR
291 inline explicit QSharedPointer(X *ptr) : value(ptr) // noexcept
292 { internalConstruct(ptr, QtSharedPointer::NormalDeleter()); }
293
294 template <class X, typename Deleter, IfCompatible<X> = true>
295 Q_NODISCARD_CTOR
296 inline QSharedPointer(X *ptr, Deleter deleter) : value(ptr) // throws
297 { internalConstruct(ptr, deleter); }
298
299 template <typename Deleter>
300 Q_NODISCARD_CTOR
301 QSharedPointer(std::nullptr_t, Deleter deleter) : value(nullptr)
302 { internalConstruct(static_cast<T *>(nullptr), deleter); }
303
304 Q_NODISCARD_CTOR
305 QSharedPointer(const QSharedPointer &other) noexcept : value(other.value), d(other.d)
306 { if (d) ref(); }
307 QSharedPointer &operator=(const QSharedPointer &other) noexcept
308 {
309 QSharedPointer copy(other);
310 swap(other&: copy);
311 return *this;
312 }
313 Q_NODISCARD_CTOR
314 QSharedPointer(QSharedPointer &&other) noexcept
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>
323 Q_NODISCARD_CTOR
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(other&: moved);
336 return *this;
337 }
338
339 template <class X, IfCompatible<X> = true>
340 Q_NODISCARD_CTOR
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 {
347 QSharedPointer copy(other);
348 swap(other&: copy);
349 return *this;
350 }
351
352 template <class X, IfCompatible<X> = true>
353 Q_NODISCARD_CTOR
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(o: other.d, actual: 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)
366 { QSharedPointer copy(t); swap(other&: copy); }
367 template <typename Deleter>
368 inline void reset(T *t, Deleter deleter)
369 { QSharedPointer copy(t, deleter); swap(other&: 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(other&: copy); }
398
399 [[nodiscard]] QWeakPointer<T> toWeakRef() const;
400
401 template <typename... Args>
402 [[nodiscard]] static QSharedPointer create(Args && ...arguments)
403 {
404 typedef QtSharedPointer::ExternalRefCountWithContiguousData<T> Private;
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;
411 QSharedPointer result(Qt::Uninitialized);
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())
442 DECLARE_TEMPLATE_COMPARE_SET(const QSharedPointer &p1, p1.data(), X *ptr, ptr)
443 DECLARE_TEMPLATE_COMPARE_SET(X *ptr, ptr, const QSharedPointer &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:
467 Q_NODISCARD_CTOR
468 explicit QSharedPointer(Qt::Initialization) {}
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 {
493 typedef QtSharedPointer::ExternalRefCountWithCustomDeleter<X, Deleter> Private;
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
502 internalSafetyCheckAdd(d, ptr);
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(expectedValue: tmp, newValue: 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(lhs&: d, rhs&: 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>
551class QWeakPointer
552{
553 typedef QtSharedPointer::ExternalRefCountData Data;
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;
566 typedef value_type *pointer;
567 typedef const value_type *const_pointer;
568 typedef value_type &reference;
569 typedef const value_type &const_reference;
570 typedef qptrdiff difference_type;
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
576 Q_NODISCARD_CTOR
577 constexpr QWeakPointer() noexcept : d(nullptr), value(nullptr) { }
578 inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
579
580 Q_NODISCARD_CTOR
581 QWeakPointer(const QWeakPointer &other) noexcept : d(other.d), value(other.value)
582 { if (d) d->weakref.ref(); }
583 Q_NODISCARD_CTOR
584 QWeakPointer(QWeakPointer &&other) noexcept
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>
593 Q_NODISCARD_CTOR
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>
601 Q_NODISCARD_CTOR
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(other&: moved);
614 return *this;
615 }
616
617 QWeakPointer &operator=(const QWeakPointer &other) noexcept
618 {
619 QWeakPointer copy(other);
620 swap(other&: 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
630 Q_NODISCARD_CTOR
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: o.d, actual: o.value);
636 return *this;
637 }
638
639 template <class X, IfCompatible<X> = true>
640 Q_NODISCARD_CTOR
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>
654 Q_NODISCARD_CTOR
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: o.d, actual: 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:
721 friend struct QtPrivate::EnableInternalData;
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>
732 Q_NODISCARD_CTOR
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 {
760struct EnableInternalData {
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>
767struct EnableInternalDataWrap : EnableInternalData {};
768}
769
770template <class T>
771class QEnableSharedFromThis
772{
773protected:
774 QEnableSharedFromThis() = default;
775 QEnableSharedFromThis(const QEnableSharedFromThis &) {}
776 QEnableSharedFromThis &operator=(const QEnableSharedFromThis &) { return *this; }
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
874 return QtSharedPointer::copyAndSetPointer(ptr, src);
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>();
888 return QtSharedPointer::copyAndSetPointer(ptr, src);
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
900 return QtSharedPointer::copyAndSetPointer(ptr, src);
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());
920 return QtSharedPointer::copyAndSetPointer(ptr, src);
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
941/// ### TODO - QTBUG-88102: make this use toStrongRef() (once support for
942/// storing non-managed QObjects in QWeakPointer is removed)
943template<typename T>
944QWeakPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
945qWeakPointerFromVariant(const QVariant &variant)
946{
947 return QWeakPointer<T>(qobject_cast<T*>(QtPrivate::EnableInternalData::internalData(p: QtSharedPointer::weakPointerFromVariant_internal(variant))));
948}
949template<typename T>
950QSharedPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
951qSharedPointerFromVariant(const QVariant &variant)
952{
953 return qSharedPointerObjectCast<T>(QtSharedPointer::sharedPointerFromVariant_internal(variant));
954}
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
998QT_END_NAMESPACE
999
1000#endif
1001