QtBase  v6.3.1
qsharedpointer_impl.h
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2021 The Qt Company Ltd.
4 ** Copyright (C) 2022 Intel Corporation.
5 ** Copyright (C) 2019 Klarälvdalens Datakonsult AB.
6 ** Contact: https://www.qt.io/licensing/
7 **
8 ** This file is part of the QtCore module of the Qt Toolkit.
9 **
10 ** $QT_BEGIN_LICENSE:LGPL$
11 ** Commercial License Usage
12 ** Licensees holding valid commercial Qt licenses may use this file in
13 ** accordance with the commercial license agreement provided with the
14 ** Software or, alternatively, in accordance with the terms contained in
15 ** a written agreement between you and The Qt Company. For licensing terms
16 ** and conditions see https://www.qt.io/terms-conditions. For further
17 ** information use the contact form at https://www.qt.io/contact-us.
18 **
19 ** GNU Lesser General Public License Usage
20 ** Alternatively, this file may be used under the terms of the GNU Lesser
21 ** General Public License version 3 as published by the Free Software
22 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
23 ** packaging of this file. Please review the following information to
24 ** ensure the GNU Lesser General Public License version 3 requirements
25 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
26 **
27 ** GNU General Public License Usage
28 ** Alternatively, this file may be used under the terms of the GNU
29 ** General Public License version 2.0 or (at your option) the GNU General
30 ** Public license version 3 or any later version approved by the KDE Free
31 ** Qt Foundation. The licenses are as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
33 ** included in the packaging of this file. Please review the following
34 ** information to ensure the GNU General Public License requirements will
35 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
36 ** https://www.gnu.org/licenses/gpl-3.0.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #ifndef Q_QDOC
43 
44 #ifndef QSHAREDPOINTER_H
45 #error Do not include qsharedpointer_impl.h directly
46 #endif
47 
48 #if 0
49 #pragma qt_sync_skip_header_check
50 #pragma qt_sync_stop_processing
51 #endif
52 
53 #if 0
54 // These macros are duplicated here to make syncqt not complain a about
55 // this header, as we have a "qt_sync_stop_processing" below, which in turn
56 // is here because this file contains a template mess and duplicates the
57 // classes found in qsharedpointer.h
60 #pragma qt_sync_stop_processing
61 #endif
62 
63 #include <new>
64 #include <QtCore/qatomic.h>
65 #include <QtCore/qobject.h> // for qobject_cast
66 #include <QtCore/qhashfunctions.h>
67 
68 #include <memory>
69 
71 
72 //
73 // forward declarations
74 //
75 template <class T> class QWeakPointer;
76 template <class T> class QSharedPointer;
77 template <class T> class QEnableSharedFromThis;
78 
79 class QVariant;
80 
81 template <class X, class T>
83 template <class X, class T>
85 template <class X, class T>
87 
88 #ifndef QT_NO_QOBJECT
89 template <class X, class T>
91 #endif
92 
93 namespace QtPrivate {
94 struct EnableInternalData;
95 }
96 
97 namespace QtSharedPointer {
98  template <class T> class ExternalRefCount;
99 
100  template <class X, class Y> QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
101 
102  // used in debug mode to verify the reuse of pointers
103  Q_CORE_EXPORT void internalSafetyCheckAdd(const void *, const volatile void *);
104  Q_CORE_EXPORT void internalSafetyCheckRemove(const void *);
105 
106  template <class T, typename Klass, typename RetVal>
107  inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)())
108  { if (t) (t->*memberDeleter)(); }
109  template <class T, typename Deleter>
110  inline void executeDeleter(T *t, Deleter d)
111  { d(t); }
112  struct NormalDeleter {};
113 
114  // this uses partial template specialization
115  template <class T> struct RemovePointer;
116  template <class T> struct RemovePointer<T *> { typedef T Type; };
117  template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; };
118  template <class T> struct RemovePointer<QWeakPointer<T> > { typedef T Type; };
119 
120  // This class is the d-pointer of QSharedPointer and QWeakPointer.
121  //
122  // It is a reference-counted reference counter. "strongref" is the inner
123  // reference counter, and it tracks the lifetime of the pointer itself.
124  // "weakref" is the outer reference counter and it tracks the lifetime of
125  // the ExternalRefCountData object.
126  //
127  // The deleter is stored in the destroyer member and is always a pointer to
128  // a static function in ExternalRefCountWithCustomDeleter or in
129  // ExternalRefCountWithContiguousData
131  {
136 
138  : destroyer(d)
139  {
142  }
145 
146  void destroy() { destroyer(this); }
147 
148 #ifndef QT_NO_QOBJECT
149  Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *);
150  Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable);
151  Q_CORE_EXPORT void checkQObjectShared(const QObject *);
152 #endif
153  inline void checkQObjectShared(...) { }
154  inline void setQObjectShared(...) { }
155 
156  // Normally, only subclasses of ExternalRefCountData are allocated
157  // One exception exists in getAndRef; that uses the global operator new
158  // to prevent a mismatch with the custom operator delete
159  inline void *operator new(std::size_t) = delete;
160  // placement new
161  inline void *operator new(std::size_t, void *ptr) noexcept { return ptr; }
162  inline void operator delete(void *ptr) { ::operator delete(ptr); }
163  inline void operator delete(void *, void *) { }
164  };
165  // sizeof(ExternalRefCountData) = 12 (32-bit) / 16 (64-bit)
166 
167  template <class T, typename Deleter>
169  {
170  Deleter deleter;
171  T *ptr;
172 
173  CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {}
175  };
176  // sizeof(CustomDeleter) = sizeof(Deleter) + sizeof(void*) + padding
177  // for Deleter = stateless functor: 8 (32-bit) / 16 (64-bit) due to padding
178  // for Deleter = function pointer: 8 (32-bit) / 16 (64-bit)
179  // for Deleter = PMF: 12 (32-bit) / 24 (64-bit) (GCC)
180 
181  // This specialization of CustomDeleter for a deleter of type NormalDeleter
182  // is an optimization: instead of storing a pointer to a function that does
183  // the deleting, we simply delete the pointer ourselves.
184  template <class T>
186  {
187  T *ptr;
188 
190  void execute() { delete ptr; }
191  };
192  // sizeof(CustomDeleter specialization) = sizeof(void*)
193 
194  // This class extends ExternalRefCountData and implements
195  // the static function that deletes the object. The pointer and the
196  // custom deleter are kept in the "extra" member so we can construct
197  // and destruct it independently of the full structure.
198  template <class T, typename Deleter>
200  {
204 
205  static inline void deleter(ExternalRefCountData *self)
206  {
207  Self *realself = static_cast<Self *>(self);
208  realself->extra.execute();
209 
210  // delete the deleter too
211  realself->extra.~CustomDeleter<T, Deleter>();
212  }
214  {
216  deleter(self);
217  }
218 
219  static inline Self *create(T *ptr, Deleter userDeleter, DestroyerFn actualDeleter)
220  {
221  Self *d = static_cast<Self *>(::operator new(sizeof(Self)));
222 
223  // initialize the two sub-objects
224  new (&d->extra) CustomDeleter<T, Deleter>(ptr, userDeleter);
225  new (d) BaseClass(actualDeleter); // can't throw
226 
227  return d;
228  }
229  private:
230  // prevent construction
234  };
235 
236  // This class extends ExternalRefCountData and adds a "T"
237  // member. That way, when the create() function is called, we allocate
238  // memory for both QSharedPointer's d-pointer and the actual object being
239  // tracked.
240  template <class T>
242  {
246 
247  static void deleter(ExternalRefCountData *self)
248  {
250  static_cast<ExternalRefCountWithContiguousData *>(self);
251  that->data.~T();
252  Q_UNUSED(that); // MSVC warns if T has a trivial destructor
253  }
255  {
257  deleter(self);
258  }
259  static void noDeleter(ExternalRefCountData *) { }
260 
262  {
264  static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData)));
265 
266  // initialize the d-pointer sub-object
267  // leave d->data uninitialized
268  new (d) Parent(destroy); // can't throw
269 
270  *ptr = &d->data;
271  return d;
272  }
273 
274  private:
275  // prevent construction
279  };
280 
281 #ifndef QT_NO_QOBJECT
284 #endif
285 } // namespace QtSharedPointer
286 
287 template <class T> class QSharedPointer
288 {
290  template <typename X>
291  using IfCompatible = typename std::enable_if<std::is_convertible<X*, T*>::value, bool>::type;
292 
293 public:
294  typedef T Type;
295  typedef T element_type;
296  typedef T value_type;
297  typedef value_type *pointer;
298  typedef const value_type *const_pointer;
300  typedef const value_type &const_reference;
302 
303  T *data() const noexcept { return value; }
304  T *get() const noexcept { return value; }
305  bool isNull() const noexcept { return !data(); }
306  explicit operator bool() const noexcept { return !isNull(); }
307  bool operator !() const noexcept { return isNull(); }
308  T &operator*() const { return *data(); }
309  T *operator->() const noexcept { return data(); }
310 
311  constexpr QSharedPointer() noexcept : value(nullptr), d(nullptr) { }
313 
314  constexpr QSharedPointer(std::nullptr_t) noexcept : value(nullptr), d(nullptr) { }
315 
316  template <class X, IfCompatible<X> = true>
317  inline explicit QSharedPointer(X *ptr) : value(ptr) // noexcept
319 
320  template <class X, typename Deleter, IfCompatible<X> = true>
321  inline QSharedPointer(X *ptr, Deleter deleter) : value(ptr) // throws
322  { internalConstruct(ptr, deleter); }
323 
324  template <typename Deleter>
325  QSharedPointer(std::nullptr_t, Deleter deleter) : value(nullptr)
326  { internalConstruct(static_cast<T *>(nullptr), deleter); }
327 
328  QSharedPointer(const QSharedPointer &other) noexcept : value(other.value), d(other.d)
329  { if (d) ref(); }
331  {
332  QSharedPointer copy(other);
333  swap(copy);
334  return *this;
335  }
337  : value(other.value), d(other.d)
338  {
339  other.d = nullptr;
340  other.value = nullptr;
341  }
343 
344  template <class X, IfCompatible<X> = true>
346  : value(other.value), d(other.d)
347  {
348  other.d = nullptr;
349  other.value = nullptr;
350  }
351 
352  template <class X, IfCompatible<X> = true>
354  {
355  QSharedPointer moved(std::move(other));
356  swap(moved);
357  return *this;
358  }
359 
360  template <class X, IfCompatible<X> = true>
361  QSharedPointer(const QSharedPointer<X> &other) noexcept : value(other.value), d(other.d)
362  { if (d) ref(); }
363 
364  template <class X, IfCompatible<X> = true>
366  {
367  QSharedPointer copy(other);
368  swap(copy);
369  return *this;
370  }
371 
372  template <class X, IfCompatible<X> = true>
374  { *this = other; }
375 
376  template <class X, IfCompatible<X> = true>
378  { internalSet(other.d, other.value); return *this; }
379 
380  inline void swap(QSharedPointer &other) noexcept
381  { this->internalSwap(other); }
382 
383  inline void reset() { clear(); }
384  inline void reset(T *t)
385  { QSharedPointer copy(t); swap(copy); }
386  template <typename Deleter>
387  inline void reset(T *t, Deleter deleter)
388  { QSharedPointer copy(t, deleter); swap(copy); }
389 
390  template <class X>
392  {
393  return qSharedPointerCast<X, T>(*this);
394  }
395 
396  template <class X>
398  {
399  return qSharedPointerDynamicCast<X, T>(*this);
400  }
401 
402  template <class X>
404  {
405  return qSharedPointerConstCast<X, T>(*this);
406  }
407 
408 #ifndef QT_NO_QOBJECT
409  template <class X>
411  {
412  return qSharedPointerObjectCast<X, T>(*this);
413  }
414 #endif
415 
416  inline void clear() { QSharedPointer copy; swap(copy); }
417 
419 
420  template <typename... Args>
422  {
424 # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
425  typename Private::DestroyerFn destroy = &Private::safetyCheckDeleter;
426 # else
427  typename Private::DestroyerFn destroy = &Private::deleter;
428 # endif
429  typename Private::DestroyerFn noDestroy = &Private::noDeleter;
431  typename std::remove_cv<T>::type *ptr;
432  result.d = Private::create(&ptr, noDestroy);
433 
434  // now initialize the data
435  new (ptr) T(std::forward<Args>(arguments)...);
436  result.value = ptr;
437  result.d->destroyer = destroy;
438  result.d->setQObjectShared(result.value, true);
439 # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
441 # endif
442  result.enableSharedFromThis(result.data());
443  return result;
444  }
445 
446 #define DECLARE_COMPARE_SET(T1, A1, T2, A2) \
447  friend bool operator==(T1, T2) noexcept \
448  { return A1 == A2; } \
449  friend bool operator!=(T1, T2) noexcept \
450  { return A1 != A2; }
451 
452 #define DECLARE_TEMPLATE_COMPARE_SET(T1, A1, T2, A2) \
453  template <typename X> \
454  friend bool operator==(T1, T2) noexcept \
455  { return A1 == A2; } \
456  template <typename X> \
457  friend bool operator!=(T1, T2) noexcept \
458  { return A1 != A2; }
459 
463  DECLARE_COMPARE_SET(const QSharedPointer &p1, p1.data(), std::nullptr_t, nullptr)
464  DECLARE_COMPARE_SET(std::nullptr_t, nullptr, const QSharedPointer &p2, p2.data())
465 #undef DECLARE_TEMPLATE_COMPARE_SET
466 #undef DECLARE_COMPARE_SET
467 
468 private:
470 
471  void deref() noexcept
472  { deref(d); }
473  static void deref(Data *dd) noexcept
474  {
475  if (!dd) return;
476  if (!dd->strongref.deref()) {
477  dd->destroy();
478  }
479  if (!dd->weakref.deref())
480  delete dd;
481  }
482 
483  template <class X>
485  {
486  ptr->initializeFromSharedPointer(constCast<typename std::remove_cv<T>::type>());
487  }
488 
489  inline void enableSharedFromThis(...) {}
490 
491  template <typename X, typename Deleter>
492  inline void internalConstruct(X *ptr, Deleter deleter)
493  {
495 # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
496  typename Private::DestroyerFn actualDeleter = &Private::safetyCheckDeleter;
497 # else
498  typename Private::DestroyerFn actualDeleter = &Private::deleter;
499 # endif
500  d = Private::create(ptr, deleter, actualDeleter);
501 
502 #ifdef QT_SHAREDPOINTER_TRACK_POINTERS
504 #endif
505  d->setQObjectShared(ptr, true);
507  }
508 
510  {
511  qt_ptr_swap(d, other.d);
512  qt_ptr_swap(this->value, other.value);
513  }
514 
515  template <class X> friend class QSharedPointer;
516  template <class X> friend class QWeakPointer;
517  template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
518  void ref() const noexcept { d->weakref.ref(); d->strongref.ref(); }
519 
520  inline void internalSet(Data *o, T *actual)
521  {
522  if (o) {
523  // increase the strongref, but never up from zero
524  // or less (-1 is used by QWeakPointer on untracked QObject)
525  int tmp = o->strongref.loadRelaxed();
526  while (tmp > 0) {
527  // try to increment from "tmp" to "tmp + 1"
528  if (o->strongref.testAndSetRelaxed(tmp, tmp + 1))
529  break; // succeeded
530  tmp = o->strongref.loadRelaxed(); // failed, try again
531  }
532 
533  if (tmp > 0) {
534  o->weakref.ref();
535  } else {
536  o->checkQObjectShared(actual);
537  o = nullptr;
538  }
539  }
540 
541  qt_ptr_swap(d, o);
542  qt_ptr_swap(this->value, actual);
543  if (!d || d->strongref.loadRelaxed() == 0)
544  this->value = nullptr;
545 
546  // dereference saved data
547  deref(o);
548  }
549 
551  Data *d;
552 };
553 
554 template <class T>
556 {
558  template <typename X>
559  using IfCompatible = typename std::enable_if<std::is_convertible<X*, T*>::value, bool>::type;
560 
561 public:
562  typedef T element_type;
563  typedef T value_type;
564  typedef value_type *pointer;
565  typedef const value_type *const_pointer;
567  typedef const value_type &const_reference;
569 
570  bool isNull() const noexcept { return d == nullptr || d->strongref.loadRelaxed() == 0 || value == nullptr; }
571  explicit operator bool() const noexcept { return !isNull(); }
572  bool operator !() const noexcept { return isNull(); }
573 
574  constexpr QWeakPointer() noexcept : d(nullptr), value(nullptr) { }
575  inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
576 
577  QWeakPointer(const QWeakPointer &other) noexcept : d(other.d), value(other.value)
578  { if (d) d->weakref.ref(); }
580  : d(other.d), value(other.value)
581  {
582  other.d = nullptr;
583  other.value = nullptr;
584  }
586 
587  template <class X, IfCompatible<X> = true>
589  : d(other.d), value(other.value)
590  {
591  other.d = nullptr;
592  other.value = nullptr;
593  }
594 
595  template <class X, IfCompatible<X> = true>
597  {
598  QWeakPointer moved(std::move(other));
599  swap(moved);
600  return *this;
601  }
602 
604  {
605  QWeakPointer copy(other);
606  swap(copy);
607  return *this;
608  }
609 
610  void swap(QWeakPointer &other) noexcept
611  {
612  qt_ptr_swap(this->d, other.d);
613  qt_ptr_swap(this->value, other.value);
614  }
615 
616  inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data())
617  { if (d) d->weakref.ref();}
619  {
620  internalSet(o.d, o.value);
621  return *this;
622  }
623 
624  template <class X, IfCompatible<X> = true>
626  { *this = o; }
627 
628  template <class X, IfCompatible<X> = true>
630  {
631  // conversion between X and T could require access to the virtual table
632  // so force the operation to go through QSharedPointer
633  *this = o.toStrongRef();
634  return *this;
635  }
636 
637  template <class X, IfCompatible<X> = true>
639  { *this = o; }
640 
641  template <class X, IfCompatible<X> = true>
643  {
644  internalSet(o.d, o.data());
645  return *this;
646  }
647 
648  inline void clear() { *this = QWeakPointer(); }
649 
650  inline QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
651  // std::weak_ptr compatibility:
652  inline QSharedPointer<T> lock() const { return toStrongRef(); }
653 
654  template <class X>
655  bool operator==(const QWeakPointer<X> &o) const noexcept
656  { return d == o.d && value == static_cast<const T *>(o.value); }
657 
658  template <class X>
659  bool operator!=(const QWeakPointer<X> &o) const noexcept
660  { return !(*this == o); }
661 
662  template <class X>
663  bool operator==(const QSharedPointer<X> &o) const noexcept
664  { return d == o.d; }
665 
666  template <class X>
667  bool operator!=(const QSharedPointer<X> &o) const noexcept
668  { return !(*this == o); }
669 
670  template <typename X>
671  friend bool operator==(const QSharedPointer<X> &p1, const QWeakPointer &p2) noexcept
672  { return p2 == p1; }
673  template <typename X>
674  friend bool operator!=(const QSharedPointer<X> &p1, const QWeakPointer &p2) noexcept
675  { return p2 != p1; }
676 
677  friend bool operator==(const QWeakPointer &p, std::nullptr_t)
678  { return p.isNull(); }
679  friend bool operator==(std::nullptr_t, const QWeakPointer &p)
680  { return p.isNull(); }
681  friend bool operator!=(const QWeakPointer &p, std::nullptr_t)
682  { return !p.isNull(); }
683  friend bool operator!=(std::nullptr_t, const QWeakPointer &p)
684  { return !p.isNull(); }
685 
686 private:
688  template <class X> friend class QSharedPointer;
689  template <class X> friend class QWeakPointer;
690  template <class X> friend class QPointer;
691 
692  template <class X>
693  inline QWeakPointer &assign(X *ptr)
694  { return *this = QWeakPointer<X>(ptr, true); }
695 
696 #ifndef QT_NO_QOBJECT
697  template <class X, IfCompatible<X> = true>
698  inline QWeakPointer(X *ptr, bool) : d(ptr ? Data::getAndRef(ptr) : nullptr), value(ptr)
699  { }
700 #endif
701 
702  inline void internalSet(Data *o, T *actual)
703  {
704  if (d == o) return;
705  if (o)
706  o->weakref.ref();
707  if (d && !d->weakref.deref())
708  delete d;
709  d = o;
710  value = actual;
711  }
712 
713  // ### TODO - QTBUG-88102: remove all users of this API; no one should ever
714  // access a weak pointer's data but the weak pointer itself
715  inline T *internalData() const noexcept
716  {
717  return d == nullptr || d->strongref.loadRelaxed() == 0 ? nullptr : value;
718  }
719 
720  Data *d;
721  T *value;
722 };
723 
724 namespace QtPrivate {
726  template <typename T>
727  static T *internalData(const QWeakPointer<T> &p) noexcept { return p.internalData(); }
728 };
729 // hack to delay name lookup to instantiation time by making
730 // EnableInternalData a dependent name:
731 template <typename T>
733 }
734 
735 template <class T>
737 {
738 protected:
742 
743 public:
744  inline QSharedPointer<T> sharedFromThis() { return QSharedPointer<T>(weakPointer); }
745  inline QSharedPointer<const T> sharedFromThis() const { return QSharedPointer<const T>(weakPointer); }
746 
747 private:
748  template <class X> friend class QSharedPointer;
749  template <class X>
750  inline void initializeFromSharedPointer(const QSharedPointer<X> &ptr) const
751  {
752  weakPointer = ptr;
753  }
754 
755  mutable QWeakPointer<T> weakPointer;
756 };
757 
758 //
759 // operator-
760 //
761 template <class T, class X>
762 Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
763 {
764  return ptr1.data() - ptr2.data();
765 }
766 template <class T, class X>
767 Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, X *ptr2)
768 {
769  return ptr1.data() - ptr2;
770 }
771 template <class T, class X>
772 Q_INLINE_TEMPLATE typename QSharedPointer<X>::difference_type operator-(T *ptr1, const QSharedPointer<X> &ptr2)
773 {
774  return ptr1 - ptr2.data();
775 }
776 
777 //
778 // operator<
779 //
780 template <class T, class X>
781 Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
782 {
783  using CT = typename std::common_type<T *, X *>::type;
784  return std::less<CT>()(ptr1.data(), ptr2.data());
785 }
786 template <class T, class X>
787 Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, X *ptr2)
788 {
789  using CT = typename std::common_type<T *, X *>::type;
790  return std::less<CT>()(ptr1.data(), ptr2);
791 }
792 template <class T, class X>
793 Q_INLINE_TEMPLATE bool operator<(T *ptr1, const QSharedPointer<X> &ptr2)
794 {
795  using CT = typename std::common_type<T *, X *>::type;
796  return std::less<CT>()(ptr1, ptr2.data());
797 }
798 
799 //
800 // qHash
801 //
802 template <class T>
803 Q_INLINE_TEMPLATE size_t qHash(const QSharedPointer<T> &ptr, size_t seed = 0)
804 {
805  return qHash(ptr.data(), seed);
806 }
807 
808 
809 template <class T>
811 {
812  return QWeakPointer<T>(*this);
813 }
814 
815 template <class T>
816 inline void swap(QSharedPointer<T> &p1, QSharedPointer<T> &p2) noexcept
817 { p1.swap(p2); }
818 
819 template <class T>
820 inline void swap(QWeakPointer<T> &p1, QWeakPointer<T> &p2) noexcept
821 { p1.swap(p2); }
822 
823 namespace QtSharedPointer {
824 // helper functions:
825  template <class X, class T>
827  {
829  result.internalSet(src.d, ptr);
830  return result;
831  }
832 }
833 
834 // cast operators
835 template <class X, class T>
837 {
838  X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
840 }
841 template <class X, class T>
843 {
844  return qSharedPointerCast<X, T>(src.toStrongRef());
845 }
846 
847 template <class X, class T>
849 {
850  X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
851  if (!ptr)
852  return QSharedPointer<X>();
854 }
855 template <class X, class T>
857 {
858  return qSharedPointerDynamicCast<X, T>(src.toStrongRef());
859 }
860 
861 template <class X, class T>
863 {
864  X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
866 }
867 template <class X, class T>
869 {
870  return qSharedPointerConstCast<X, T>(src.toStrongRef());
871 }
872 
873 template <class X, class T>
874 Q_INLINE_TEMPLATE
876 {
877  return qSharedPointerCast<X, T>(src).toWeakRef();
878 }
879 
880 #ifndef QT_NO_QOBJECT
881 template <class X, class T>
883 {
884  X *ptr = qobject_cast<X *>(src.data());
886 }
887 template <class X, class T>
889 {
890  return qSharedPointerObjectCast<X>(src.toStrongRef());
891 }
892 
893 template <class X, class T>
896 {
898 }
899 template <class X, class T>
902 {
904 }
905 
908 template<typename T>
911 {
913 }
914 template<typename T>
917 {
918  return qSharedPointerObjectCast<T>(QtSharedPointer::sharedPointerFromVariant_internal(variant));
919 }
920 
921 // std::shared_ptr helpers
922 
923 template <typename X, class T>
924 std::shared_ptr<X> qobject_pointer_cast(const std::shared_ptr<T> &src)
925 {
926  using element_type = typename std::shared_ptr<X>::element_type;
927  return std::shared_ptr<X>(src, qobject_cast<element_type *>(src.get()));
928 }
929 
930 template <typename X, class T>
931 std::shared_ptr<X> qobject_pointer_cast(std::shared_ptr<T> &&src)
932 {
933  using element_type = typename std::shared_ptr<X>::element_type;
934  auto castResult = qobject_cast<element_type *>(src.get());
935  if (castResult) {
936  // C++2a's move aliasing constructor will leave src empty.
937  // Before C++2a we don't really know if the compiler has support for it.
938  // The move aliasing constructor is the resolution for LWG2996,
939  // which does not impose a feature-testing macro. So: clear src.
940  return std::shared_ptr<X>(std::exchange(src, nullptr), castResult);
941  }
942  return std::shared_ptr<X>();
943 }
944 
945 template <typename X, class T>
946 std::shared_ptr<X> qSharedPointerObjectCast(const std::shared_ptr<T> &src)
947 {
948  return qobject_pointer_cast<X>(src);
949 }
950 
951 template <typename X, class T>
952 std::shared_ptr<X> qSharedPointerObjectCast(std::shared_ptr<T> &&src)
953 {
954  return qobject_pointer_cast<X>(std::move(src));
955 }
956 
957 #endif
958 
961 
962 
964 
965 #endif
#define value
[5]
bool ref() noexcept
Definition: qbasicatomic.h:101
bool deref() noexcept
Definition: qbasicatomic.h:102
void storeRelaxed(T newValue) noexcept
Definition: qbasicatomic.h:91
T loadRelaxed() const noexcept
Definition: qbasicatomic.h:90
bool operator<(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
A base class that allows obtaining a QSharedPointer for an object already managed by a shared pointer...
QSharedPointer< T > sharedFromThis()
QEnableSharedFromThis(const QEnableSharedFromThis &)
QEnableSharedFromThis & operator=(const QEnableSharedFromThis &)
QEnableSharedFromThis()=default
QSharedPointer< const T > sharedFromThis() const
template< typename Enum > size_t qHash(QFlags< Enum > flags, size_t seed=0) noexcept
QMargins operator-(const QMargins &m1, const QMargins &m2)
Definition: qmargins.h:168
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
template< class T > T qobject_cast(const QObject *object)
Definition: qobject.h:478
void swap(QPixmap &other) noexcept
Definition: qpixmap.h:79
The QPointer class is a template class that provides guarded pointers to QObject.
Definition: qpointer.h:54
The QSharedPointer class holds a strong reference to a shared pointer.
template< class X, class T > std::shared_ptr< X > qobject_pointer_cast(const std::shared_ptr< T > &src)
QSharedPointer(const QWeakPointer< X > &other)
QSharedPointer(X *ptr, Deleter deleter)
bool isNull() const noexcept
static void deref(Data *dd) noexcept
QSharedPointer & operator=(const QSharedPointer< X > &other)
QSharedPointer(const QSharedPointer &other) noexcept
QSharedPointer< X > constCast() const
DECLARE_TEMPLATE_COMPARE_SET(const QSharedPointer &p1, p1.data(), const QSharedPointer< X > &p2, p2.data()) private
bool operator!() const noexcept
void enableSharedFromThis(const QEnableSharedFromThis< X > *ptr)
constexpr QSharedPointer() noexcept
friend class QSharedPointer
template< class X > template< class T > QSharedPointer< X > qSharedPointerObjectCast(const QSharedPointer< T > &src)
The qSharedPointerObjectCast function is for casting a shared pointer.
QWeakPointer< T > toWeakRef() const
QSharedPointer< X > objectCast() const
T * data() const noexcept
void reset(T *t, Deleter deleter)
void internalSet(Data *o, T *actual)
QSharedPointer< X > dynamicCast() const
QSharedPointer(QSharedPointer &&other) noexcept
void enableSharedFromThis(...)
const value_type & const_reference
void deref() noexcept
QSharedPointer & operator=(QSharedPointer< X > &&other) noexcept
QSharedPointer(std::nullptr_t, Deleter deleter)
T * get() const noexcept
QSharedPointer< T > & operator=(const QWeakPointer< X > &other)
QSharedPointer(QSharedPointer< X > &&other) noexcept
void internalConstruct(X *ptr, Deleter deleter)
const value_type * const_pointer
void internalSwap(QSharedPointer &other) noexcept
constexpr QSharedPointer(std::nullptr_t) noexcept
static QSharedPointer create(Args &&...arguments)
template< class X > template< class T > QSharedPointer< X > qSharedPointerCast(const QSharedPointer< T > &other)
QSharedPointer & operator=(const QSharedPointer &other) noexcept
value_type * pointer
QSharedPointer< X > staticCast() const
value_type & reference
T * operator->() const noexcept
void swap(QSharedPointer &other) noexcept
void ref() const noexcept
template< class X > template< class T > QSharedPointer< X > qSharedPointerConstCast(const QSharedPointer< T > &src)
template< class X > template< class T > QSharedPointer< X > qSharedPointerDynamicCast(const QSharedPointer< T > &src)
QSharedPointer(const QSharedPointer< X > &other) noexcept
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:95
The QWeakPointer class holds a weak reference to a shared pointer.
friend bool operator==(const QWeakPointer &p, std::nullptr_t)
const value_type & const_reference
friend bool operator!=(const QWeakPointer &p, std::nullptr_t)
constexpr QWeakPointer() noexcept
QWeakPointer(QWeakPointer< X > &&other) noexcept
QWeakPointer(const QWeakPointer &other) noexcept
friend bool operator==(const QSharedPointer< X > &p1, const QWeakPointer &p2) noexcept
QWeakPointer(QWeakPointer &&other) noexcept
QWeakPointer & operator=(const QWeakPointer< X > &o)
QWeakPointer(const QWeakPointer< X > &o)
QWeakPointer & operator=(QWeakPointer< X > &&other) noexcept
QWeakPointer & operator=(const QWeakPointer &other) noexcept
friend bool operator==(std::nullptr_t, const QWeakPointer &p)
qptrdiff difference_type
friend bool operator!=(const QSharedPointer< X > &p1, const QWeakPointer &p2) noexcept
bool operator==(const QSharedPointer< X > &o) const noexcept
QWeakPointer(const QSharedPointer< X > &o)
QSharedPointer< T > toStrongRef() const
QWeakPointer & operator=(const QSharedPointer< T > &o)
bool operator!() const noexcept
QWeakPointer & operator=(const QSharedPointer< X > &o)
bool operator==(const QWeakPointer< X > &o) const noexcept
QSharedPointer< T > lock() const
bool operator!=(const QWeakPointer< X > &o) const noexcept
const value_type * const_pointer
bool isNull() const noexcept
friend class QWeakPointer
template< class X > template< class T > QWeakPointer< X > qWeakPointerCast(const QWeakPointer< T > &src)
bool operator!=(const QSharedPointer< X > &o) const noexcept
friend bool operator!=(std::nullptr_t, const QWeakPointer &p)
value_type * pointer
QWeakPointer(const QSharedPointer< T > &o)
value_type & reference
void swap(QWeakPointer &other) noexcept
#define T(x)
Definition: main.cpp:42
QPixmap p2
QPixmap p1
[0]
QList< QVariant > arguments
auto it unsigned count const
Definition: hb-iter.hh:848
constexpr Initialization Uninitialized
Definition: qnamespace.h:1613
Initialization
Definition: qnamespace.h:1610
Q_CORE_EXPORT QWeakPointer< QObject > weakPointerFromVariant_internal(const QVariant &variant)
Q_CORE_EXPORT void internalSafetyCheckRemove(const void *)
QSharedPointer< X > copyAndSetPointer(X *ptr, const QSharedPointer< Y > &src)
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)
Definition: qfloat16.h:381
void
Definition: png.h:1080
EGLOutputLayerEXT EGLint EGLAttrib value
ptrdiff_t qptrdiff
Definition: qglobal.h:307
#define Q_DISABLE_COPY(Class)
Definition: qglobal.h:515
#define QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(Class)
Definition: qglobal.h:556
GLenum type
Definition: qopengl.h:270
GLenum src
GLboolean enable
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLdouble GLdouble t
[9]
Definition: qopenglext.h:243
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
QWeakPointer< typename std::enable_if< QtPrivate::IsPointerToTypeDerivedFromQObject< T * >::Value, T >::type > qWeakPointerFromVariant(const QVariant &variant)
Q_DECLARE_TYPEINFO_BODY(QWeakPointer< T >, Q_RELOCATABLE_TYPE)
QSharedPointer< typename std::enable_if< QtPrivate::IsPointerToTypeDerivedFromQObject< T * >::Value, T >::type > qSharedPointerFromVariant(const QVariant &variant)
void swap(QSharedPointer< T > &p1, QSharedPointer< T > &p2) noexcept
#define DECLARE_COMPARE_SET(T1, A1, T2, A2)
@ Q_RELOCATABLE_TYPE
Definition: qtypeinfo.h:156
Q_UNUSED(salary)
[21]
HB_EXTERN hb_font_get_glyph_func_t void hb_destroy_func_t destroy
QObject::connect nullptr
QVariant variant
[1]
QSharedPointer< T > other(t)
[5]
view create()
QDBusVariant Type
Definition: main.cpp:58
static T * internalData(const QWeakPointer< T > &p) noexcept
void(* DestroyerFn)(ExternalRefCountData *)
Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable)
Q_CORE_EXPORT void checkQObjectShared(const QObject *)
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 void safetyCheckDeleter(ExternalRefCountData *self)
static Self * create(T *ptr, Deleter userDeleter, DestroyerFn actualDeleter)
static void deleter(ExternalRefCountData *self)
Definition: main.cpp:38
#define CT(E)