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

source code of qtbase/src/corelib/tools/qsharedpointer_impl.h