1/****************************************************************************
2**
3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Digia. For licensing terms and
14** conditions see http://qt.digia.com/licensing. For further information
15** use the contact form at http://qt.digia.com/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 2.1 requirements
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24**
25** In addition, as a special exception, Digia gives you certain additional
26** rights. These rights are described in the Digia Qt LGPL Exception
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28**
29** GNU General Public License Usage
30** Alternatively, this file may be used under the terms of the GNU
31** General Public License version 3.0 as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL included in the
33** packaging of this file. Please review the following information to
34** ensure the GNU General Public License version 3.0 requirements will be
35** met: http://www.gnu.org/copyleft/gpl.html.
36**
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// These macros are duplicated here to make syncqt not complain a about
50// this header, as we have a "qt_sync_stop_processing" below, which in turn
51// is here because this file contains a template mess and duplicates the
52// classes found in qsharedpointer.h
53QT_BEGIN_HEADER
54QT_BEGIN_NAMESPACE
55QT_MODULE(Core)
56QT_END_NAMESPACE
57QT_END_HEADER
58#pragma qt_sync_stop_processing
59#endif
60
61#include <new>
62#include <QtCore/qatomic.h>
63#include <QtCore/qobject.h> // for qobject_cast
64
65QT_BEGIN_HEADER
66
67QT_BEGIN_NAMESPACE
68
69QT_MODULE(Core)
70
71// Macro QSHAREDPOINTER_VERIFY_AUTO_CAST
72// generates a compiler error if the following construct isn't valid:
73// T *ptr1;
74// X *ptr2 = ptr1;
75//
76#ifdef QT_NO_DEBUG
77# define QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X) qt_noop()
78#else
79
80template<typename T> inline void qt_sharedpointer_cast_check(T *) { }
81# define QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X) \
82 qt_sharedpointer_cast_check<T>(static_cast<X *>(0))
83#endif
84
85//
86// forward declarations
87//
88template <class T> class QWeakPointer;
89template <class T> class QSharedPointer;
90
91template <class X, class T>
92QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &ptr);
93template <class X, class T>
94QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &ptr);
95template <class X, class T>
96QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &ptr);
97
98#ifndef QT_NO_QOBJECT
99template <class X, class T>
100QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &ptr);
101#endif
102
103namespace QtSharedPointer {
104 template <class T> class InternalRefCount;
105 template <class T> class ExternalRefCount;
106
107 template <class X, class Y> QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
108
109 // used in debug mode to verify the reuse of pointers
110 Q_CORE_EXPORT void internalSafetyCheckAdd2(const void *, const volatile void *);
111 Q_CORE_EXPORT void internalSafetyCheckRemove2(const void *);
112
113 template <class T, typename Klass, typename RetVal>
114 inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)())
115 { (t->*memberDeleter)(); }
116 template <class T, typename Deleter>
117 inline void executeDeleter(T *t, Deleter d)
118 { d(t); }
119 template <class T> inline void normalDeleter(T *t) { delete t; }
120
121 // this uses partial template specialization
122 template <class T> struct RemovePointer;
123 template <class T> struct RemovePointer<T *> { typedef T Type; };
124 template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; };
125 template <class T> struct RemovePointer<QWeakPointer<T> > { typedef T Type; };
126
127 // This class provides the basic functionality of a pointer wrapper.
128 // Its existence is mostly legacy, since originally QSharedPointer
129 // could also be used for internally-refcounted objects.
130 template <class T>
131 class Basic
132 {
133#ifndef Q_CC_NOKIAX86
134 typedef T *Basic:: *RestrictedBool;
135#endif
136 public:
137 typedef T Type;
138 typedef T element_type;
139 typedef T value_type;
140 typedef value_type *pointer;
141 typedef const value_type *const_pointer;
142 typedef value_type &reference;
143 typedef const value_type &const_reference;
144 typedef qptrdiff difference_type;
145
146 inline T *data() const { return value; }
147 inline bool isNull() const { return !data(); }
148#ifndef Q_CC_NOKIAX86
149 inline operator RestrictedBool() const { return isNull() ? 0 : &Basic::value; }
150#else
151 inline operator bool() const { return isNull() ? 0 : &Basic::value; }
152#endif
153 inline bool operator !() const { return isNull(); }
154 inline T &operator*() const { return *data(); }
155 inline T *operator->() const { return data(); }
156
157 protected:
158 inline Basic(T *ptr = 0) : value(ptr) { }
159 inline Basic(Qt::Initialization) { }
160 // ~Basic();
161
162 inline void internalConstruct(T *ptr)
163 {
164 value = ptr;
165 }
166
167#if defined(Q_NO_TEMPLATE_FRIENDS)
168 public:
169#else
170 template <class X> friend class QT_PREPEND_NAMESPACE(QWeakPointer);
171#endif
172
173 Type *value;
174 };
175
176 // This class is the d-pointer of QSharedPointer and QWeakPointer.
177 //
178 // It is a reference-counted reference counter. "strongref" is the inner
179 // reference counter, and it tracks the lifetime of the pointer itself.
180 // "weakref" is the outer reference counter and it tracks the lifetime of
181 // the ExternalRefCountData object.
182 struct ExternalRefCountData
183 {
184 QBasicAtomicInt weakref;
185 QBasicAtomicInt strongref;
186
187 inline ExternalRefCountData()
188 {
189 strongref = 1;
190 weakref = 1;
191 }
192 inline ExternalRefCountData(Qt::Initialization) { }
193 virtual inline ~ExternalRefCountData() { Q_ASSERT(!weakref); Q_ASSERT(strongref <= 0); }
194
195 // overridden by derived classes
196 // returns false to indicate caller should delete the pointer
197 // returns true in case it has already done so
198 virtual inline bool destroy() { return false; }
199
200#ifndef QT_NO_QOBJECT
201 Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *);
202 Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable);
203#endif
204 inline void setQObjectShared(...) { }
205 };
206 // sizeof(ExternalRefCount) = 12 (32-bit) / 16 (64-bit)
207
208 // This class extends ExternalRefCountData with a pointer
209 // to a function, which is called by the destroy() function.
210 struct ExternalRefCountWithDestroyFn: public ExternalRefCountData
211 {
212 typedef void (*DestroyerFn)(ExternalRefCountData *);
213 DestroyerFn destroyer;
214
215 inline ExternalRefCountWithDestroyFn(DestroyerFn d)
216 : destroyer(d)
217 { }
218
219 inline bool destroy() { destroyer(this); return true; }
220 inline void operator delete(void *ptr) { ::operator delete(ptr); }
221 inline void operator delete(void *, void *) { }
222 };
223 // sizeof(ExternalRefCountWithDestroyFn) = 16 (32-bit) / 24 (64-bit)
224
225 // This class extends ExternalRefCountWithDestroyFn and implements
226 // the static function that deletes the object. The pointer and the
227 // custom deleter are kept in the "extra" member.
228 template <class T, typename Deleter>
229 struct ExternalRefCountWithCustomDeleter: public ExternalRefCountWithDestroyFn
230 {
231 typedef ExternalRefCountWithCustomDeleter Self;
232 typedef ExternalRefCountWithDestroyFn BaseClass;
233
234 struct CustomDeleter
235 {
236 Deleter deleter;
237 T *ptr;
238
239 inline CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {}
240 };
241 CustomDeleter extra;
242 // sizeof(CustomDeleter) = sizeof(Deleter) + sizeof(void*)
243 // for Deleter = function pointer: 8 (32-bit) / 16 (64-bit)
244 // for Deleter = PMF: 12 (32-bit) / 24 (64-bit) (GCC)
245
246 static inline void deleter(ExternalRefCountData *self)
247 {
248 Self *realself = static_cast<Self *>(self);
249 executeDeleter(realself->extra.ptr, realself->extra.deleter);
250
251 // delete the deleter too
252 realself->extra.~CustomDeleter();
253 }
254 static void safetyCheckDeleter(ExternalRefCountData *self)
255 {
256 internalSafetyCheckRemove2(self);
257 deleter(self);
258 }
259
260 static inline Self *create(T *ptr, Deleter userDeleter)
261 {
262# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
263 DestroyerFn destroy = &safetyCheckDeleter;
264# else
265 DestroyerFn destroy = &deleter;
266# endif
267 Self *d = static_cast<Self *>(::operator new(sizeof(Self)));
268
269 // initialize the two sub-objects
270 new (&d->extra) CustomDeleter(ptr, userDeleter);
271 new (d) BaseClass(destroy); // can't throw
272
273 return d;
274 }
275 private:
276 // prevent construction and the emission of virtual symbols
277 ExternalRefCountWithCustomDeleter();
278 ~ExternalRefCountWithCustomDeleter();
279 };
280
281 // This class extends ExternalRefCountWithDestroyFn and adds a "T"
282 // member. That way, when the create() function is called, we allocate
283 // memory for both QSharedPointer's d-pointer and the actual object being
284 // tracked.
285 template <class T>
286 struct ExternalRefCountWithContiguousData: public ExternalRefCountWithDestroyFn
287 {
288 typedef ExternalRefCountWithDestroyFn Parent;
289 T data;
290
291 static void deleter(ExternalRefCountData *self)
292 {
293 ExternalRefCountWithContiguousData *that =
294 static_cast<ExternalRefCountWithContiguousData *>(self);
295 that->data.~T();
296 }
297 static void safetyCheckDeleter(ExternalRefCountData *self)
298 {
299 internalSafetyCheckRemove2(self);
300 deleter(self);
301 }
302
303 static inline ExternalRefCountData *create(T **ptr)
304 {
305# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
306 DestroyerFn destroy = &safetyCheckDeleter;
307# else
308 DestroyerFn destroy = &deleter;
309# endif
310 ExternalRefCountWithContiguousData *d =
311 static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData)));
312
313 // initialize the d-pointer sub-object
314 // leave d->data uninitialized
315 new (d) Parent(destroy); // can't throw
316
317 *ptr = &d->data;
318 return d;
319 }
320
321 private:
322 // prevent construction and the emission of virtual symbols
323 ExternalRefCountWithContiguousData();
324 ~ExternalRefCountWithContiguousData();
325 };
326
327 // This is the main body of QSharedPointer. It implements the
328 // external reference counting functionality.
329 template <class T>
330 class ExternalRefCount: public Basic<T>
331 {
332 protected:
333 typedef ExternalRefCountData Data;
334
335 inline void deref()
336 { deref(d, this->value); }
337 static inline void deref(Data *d, T *value)
338 {
339 if (!d) return;
340 if (!d->strongref.deref()) {
341 if (!d->destroy())
342 delete value;
343 }
344 if (!d->weakref.deref())
345 delete d;
346 }
347
348 inline void internalConstruct(T *ptr)
349 {
350#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
351 internalConstruct<void (*)(T *)>(ptr, normalDeleter);
352#else
353 if (ptr)
354 d = new Data;
355 else
356 d = 0;
357 internalFinishConstruction(ptr);
358#endif
359 }
360
361 template <typename Deleter>
362 inline void internalConstruct(T *ptr, Deleter deleter)
363 {
364 if (ptr)
365 d = ExternalRefCountWithCustomDeleter<T, Deleter>::create(ptr, deleter);
366 else
367 d = 0;
368 internalFinishConstruction(ptr);
369 }
370
371 inline void internalCreate()
372 {
373 T *ptr;
374 d = ExternalRefCountWithContiguousData<T>::create(&ptr);
375 Basic<T>::internalConstruct(ptr);
376 }
377
378 inline void internalFinishConstruction(T *ptr)
379 {
380 Basic<T>::internalConstruct(ptr);
381#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
382 if (ptr) internalSafetyCheckAdd2(d, ptr);
383#endif
384 if (ptr) d->setQObjectShared(ptr, true);
385 }
386
387 inline ExternalRefCount() : d(0) { }
388 inline ExternalRefCount(Qt::Initialization i) : Basic<T>(i) { }
389
390 inline ExternalRefCount(T *ptr) : Basic<T>(Qt::Uninitialized) // throws
391 { internalConstruct(ptr); }
392 template <typename Deleter>
393 inline ExternalRefCount(T *ptr, Deleter deleter) : Basic<T>(Qt::Uninitialized) // throws
394 { internalConstruct(ptr, deleter); }
395
396 inline ExternalRefCount(const ExternalRefCount<T> &other) : Basic<T>(other), d(other.d)
397 { if (d) ref(); }
398 template <class X>
399 inline ExternalRefCount(const ExternalRefCount<X> &other) : Basic<T>(other.value), d(other.d)
400 { if (d) ref(); }
401 inline ~ExternalRefCount() { deref(); }
402
403 template <class X>
404 inline void internalCopy(const ExternalRefCount<X> &other)
405 {
406 Data *o = other.d;
407 T *actual = other.value;
408 if (o)
409 other.ref();
410 qSwap(d, o);
411 qSwap(this->value, actual);
412 deref(o, actual);
413 }
414
415 inline void internalSwap(ExternalRefCount &other)
416 {
417 qSwap(d, other.d);
418 qSwap(this->value, other.value);
419 }
420
421#if defined(Q_NO_TEMPLATE_FRIENDS)
422 public:
423#else
424 template <class X> friend class ExternalRefCount;
425 template <class X> friend class QT_PREPEND_NAMESPACE(QWeakPointer);
426 template <class X, class Y> friend QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
427#endif
428 inline void ref() const { d->weakref.ref(); d->strongref.ref(); }
429
430 inline void internalSet(Data *o, T *actual)
431 {
432 if (o) {
433 // increase the strongref, but never up from zero
434 // or less (-1 is used by QWeakPointer on untracked QObject)
435 register int tmp = o->strongref;
436 while (tmp > 0) {
437 // try to increment from "tmp" to "tmp + 1"
438 if (o->strongref.testAndSetRelaxed(tmp, tmp + 1))
439 break; // succeeded
440 tmp = o->strongref; // failed, try again
441 }
442
443 if (tmp > 0)
444 o->weakref.ref();
445 else
446 o = 0;
447 }
448
449 qSwap(d, o);
450 qSwap(this->value, actual);
451 if (!d || d->strongref == 0)
452 this->value = 0;
453
454 // dereference saved data
455 deref(o, actual);
456 }
457
458 Data *d;
459
460 private:
461 template<class X> ExternalRefCount(const InternalRefCount<X> &);
462 };
463} // namespace QtSharedPointer
464
465template <class T>
466class QSharedPointer: public QtSharedPointer::ExternalRefCount<T>
467{
468 typedef typename QtSharedPointer::ExternalRefCount<T> BaseClass;
469public:
470 inline QSharedPointer() { }
471 // inline ~QSharedPointer() { }
472
473 inline explicit QSharedPointer(T *ptr) : BaseClass(ptr) // throws
474 { }
475
476 template <typename Deleter>
477 inline QSharedPointer(T *ptr, Deleter d) : BaseClass(ptr, d) // throws
478 { }
479
480 inline QSharedPointer(const QSharedPointer<T> &other) : BaseClass(other) { }
481 inline QSharedPointer<T> &operator=(const QSharedPointer<T> &other)
482 {
483 BaseClass::internalCopy(other);
484 return *this;
485 }
486#ifdef Q_COMPILER_RVALUE_REFS
487 inline QSharedPointer<T> &operator=(QSharedPointer<T> &&other)
488 {
489 QSharedPointer<T>::internalSwap(other);
490 return *this;
491 }
492#endif
493
494 template <class X>
495 inline QSharedPointer(const QSharedPointer<X> &other) : BaseClass(other)
496 { }
497
498 template <class X>
499 inline QSharedPointer<T> &operator=(const QSharedPointer<X> &other)
500 {
501 QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
502 BaseClass::internalCopy(other);
503 return *this;
504 }
505
506 template <class X>
507 inline QSharedPointer(const QWeakPointer<X> &other) : BaseClass(Qt::Uninitialized)
508 { this->d = 0; *this = other; }
509
510 template <class X>
511 inline QSharedPointer<T> &operator=(const QWeakPointer<X> &other)
512 { BaseClass::internalSet(other.d, other.value); return *this; }
513
514 inline void swap(QSharedPointer &other)
515 { QSharedPointer<T>::internalSwap(other); }
516
517 template <class X>
518 QSharedPointer<X> staticCast() const
519 {
520 return qSharedPointerCast<X, T>(*this);
521 }
522
523 template <class X>
524 QSharedPointer<X> dynamicCast() const
525 {
526 return qSharedPointerDynamicCast<X, T>(*this);
527 }
528
529 template <class X>
530 QSharedPointer<X> constCast() const
531 {
532 return qSharedPointerConstCast<X, T>(*this);
533 }
534
535#ifndef QT_NO_QOBJECT
536 template <class X>
537 QSharedPointer<X> objectCast() const
538 {
539 return qSharedPointerObjectCast<X, T>(*this);
540 }
541#endif
542
543 inline void clear() { *this = QSharedPointer<T>(); }
544
545 QWeakPointer<T> toWeakRef() const;
546
547protected:
548 inline explicit QSharedPointer(Qt::Initialization i) : BaseClass(i) {}
549
550public:
551 static inline QSharedPointer<T> create()
552 {
553 QSharedPointer<T> result(Qt::Uninitialized);
554 result.internalCreate();
555
556 // now initialize the data
557 new (result.data()) T();
558 result.internalFinishConstruction(result.data());
559 return result;
560 }
561};
562
563template <class T>
564class QWeakPointer
565{
566#ifndef Q_CC_NOKIAX86
567 typedef T *QWeakPointer:: *RestrictedBool;
568#endif
569 typedef QtSharedPointer::ExternalRefCountData Data;
570
571public:
572 typedef T element_type;
573 typedef T value_type;
574 typedef value_type *pointer;
575 typedef const value_type *const_pointer;
576 typedef value_type &reference;
577 typedef const value_type &const_reference;
578 typedef qptrdiff difference_type;
579
580 inline bool isNull() const { return d == 0 || d->strongref == 0 || value == 0; }
581#ifndef Q_CC_NOKIAX86
582 inline operator RestrictedBool() const { return isNull() ? 0 : &QWeakPointer::value; }
583#else
584 inline operator bool() const { return isNull() ? 0 : &QWeakPointer::value; }
585#endif
586 inline bool operator !() const { return isNull(); }
587 inline T *data() const { return d == 0 || d->strongref == 0 ? 0 : value; }
588
589 inline QWeakPointer() : d(0), value(0) { }
590 inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
591
592#ifndef QT_NO_QOBJECT
593 // special constructor that is enabled only if X derives from QObject
594 template <class X>
595 inline QWeakPointer(X *ptr) : d(ptr ? Data::getAndRef(ptr) : 0), value(ptr)
596 { }
597#endif
598 template <class X>
599 inline QWeakPointer &operator=(X *ptr)
600 { return *this = QWeakPointer(ptr); }
601
602 inline QWeakPointer(const QWeakPointer<T> &o) : d(o.d), value(o.value)
603 { if (d) d->weakref.ref(); }
604 inline QWeakPointer<T> &operator=(const QWeakPointer<T> &o)
605 {
606 internalSet(o.d, o.value);
607 return *this;
608 }
609
610 inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data())
611 { if (d) d->weakref.ref();}
612 inline QWeakPointer<T> &operator=(const QSharedPointer<T> &o)
613 {
614 internalSet(o.d, o.value);
615 return *this;
616 }
617
618 template <class X>
619 inline QWeakPointer(const QWeakPointer<X> &o) : d(0), value(0)
620 { *this = o; }
621
622 template <class X>
623 inline QWeakPointer<T> &operator=(const QWeakPointer<X> &o)
624 {
625 // conversion between X and T could require access to the virtual table
626 // so force the operation to go through QSharedPointer
627 *this = o.toStrongRef();
628 return *this;
629 }
630
631 template <class X>
632 inline bool operator==(const QWeakPointer<X> &o) const
633 { return d == o.d && value == static_cast<const T *>(o.value); }
634
635 template <class X>
636 inline bool operator!=(const QWeakPointer<X> &o) const
637 { return !(*this == o); }
638
639 template <class X>
640 inline QWeakPointer(const QSharedPointer<X> &o) : d(0), value(0)
641 { *this = o; }
642
643 template <class X>
644 inline QWeakPointer<T> &operator=(const QSharedPointer<X> &o)
645 {
646 QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
647 internalSet(o.d, o.data());
648 return *this;
649 }
650
651 template <class X>
652 inline bool operator==(const QSharedPointer<X> &o) const
653 { return d == o.d; }
654
655 template <class X>
656 inline bool operator!=(const QSharedPointer<X> &o) const
657 { return !(*this == o); }
658
659 inline void clear() { *this = QWeakPointer<T>(); }
660
661 inline QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
662
663#if defined(QWEAKPOINTER_ENABLE_ARROW)
664 inline T *operator->() const { return data(); }
665#endif
666
667private:
668
669#if defined(Q_NO_TEMPLATE_FRIENDS)
670public:
671#else
672 template <class X> friend class QSharedPointer;
673#endif
674
675 inline void internalSet(Data *o, T *actual)
676 {
677 if (d == o) return;
678 if (o)
679 o->weakref.ref();
680 if (d && !d->weakref.deref())
681 delete d;
682 d = o;
683 value = actual;
684 }
685
686 Data *d;
687 T *value;
688};
689
690//
691// operator== and operator!=
692//
693template <class T, class X>
694bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
695{
696 return ptr1.data() == ptr2.data();
697}
698template <class T, class X>
699bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
700{
701 return ptr1.data() != ptr2.data();
702}
703
704template <class T, class X>
705bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2)
706{
707 return ptr1.data() == ptr2;
708}
709template <class T, class X>
710bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2)
711{
712 return ptr1 == ptr2.data();
713}
714template <class T, class X>
715bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2)
716{
717 return !(ptr1 == ptr2);
718}
719template <class T, class X>
720bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2)
721{
722 return !(ptr2 == ptr1);
723}
724
725template <class T, class X>
726bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
727{
728 return ptr2 == ptr1;
729}
730template <class T, class X>
731bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
732{
733 return ptr2 != ptr1;
734}
735
736//
737// operator-
738//
739template <class T, class X>
740Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
741{
742 return ptr1.data() - ptr2.data();
743}
744template <class T, class X>
745Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, X *ptr2)
746{
747 return ptr1.data() - ptr2;
748}
749template <class T, class X>
750Q_INLINE_TEMPLATE typename QSharedPointer<X>::difference_type operator-(T *ptr1, const QSharedPointer<X> &ptr2)
751{
752 return ptr1 - ptr2.data();
753}
754
755//
756// operator<
757//
758template <class T, class X>
759Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
760{
761 return ptr1.data() < ptr2.data();
762}
763template <class T, class X>
764Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, X *ptr2)
765{
766 return ptr1.data() < ptr2;
767}
768template <class T, class X>
769Q_INLINE_TEMPLATE bool operator<(T *ptr1, const QSharedPointer<X> &ptr2)
770{
771 return ptr1 < ptr2.data();
772}
773
774//
775// qHash
776//
777template <class T> inline uint qHash(const T *key); // defined in qhash.h
778template <class T>
779Q_INLINE_TEMPLATE uint qHash(const QSharedPointer<T> &ptr)
780{
781 return QT_PREPEND_NAMESPACE(qHash)<T>(ptr.data());
782}
783
784
785template <class T>
786Q_INLINE_TEMPLATE QWeakPointer<T> QSharedPointer<T>::toWeakRef() const
787{
788 return QWeakPointer<T>(*this);
789}
790
791template <class T>
792inline void qSwap(QSharedPointer<T> &p1, QSharedPointer<T> &p2)
793{
794 p1.swap(p2);
795}
796
797#ifndef QT_NO_STL
798QT_END_NAMESPACE
799namespace std {
800 template <class T>
801 inline void swap(QT_PREPEND_NAMESPACE(QSharedPointer)<T> &p1, QT_PREPEND_NAMESPACE(QSharedPointer)<T> &p2)
802 { p1.swap(p2); }
803}
804QT_BEGIN_NAMESPACE
805#endif
806
807namespace QtSharedPointer {
808// helper functions:
809 template <class X, class T>
810 Q_INLINE_TEMPLATE QSharedPointer<X> copyAndSetPointer(X *ptr, const QSharedPointer<T> &src)
811 {
812 QSharedPointer<X> result;
813 result.internalSet(src.d, ptr);
814 return result;
815 }
816}
817
818// cast operators
819template <class X, class T>
820Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &src)
821{
822 register X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
823 return QtSharedPointer::copyAndSetPointer(ptr, src);
824}
825template <class X, class T>
826Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &src)
827{
828 return qSharedPointerCast<X, T>(src.toStrongRef());
829}
830
831template <class X, class T>
832Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src)
833{
834 register X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
835 if (!ptr)
836 return QSharedPointer<X>();
837 return QtSharedPointer::copyAndSetPointer(ptr, src);
838}
839template <class X, class T>
840Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src)
841{
842 return qSharedPointerDynamicCast<X, T>(src.toStrongRef());
843}
844
845template <class X, class T>
846Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src)
847{
848 register X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
849 return QtSharedPointer::copyAndSetPointer(ptr, src);
850}
851template <class X, class T>
852Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src)
853{
854 return qSharedPointerConstCast<X, T>(src.toStrongRef());
855}
856
857template <class X, class T>
858Q_INLINE_TEMPLATE
859QWeakPointer<X> qWeakPointerCast(const QSharedPointer<T> &src)
860{
861 return qSharedPointerCast<X, T>(src).toWeakRef();
862}
863
864#ifndef QT_NO_QOBJECT
865template <class X, class T>
866Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src)
867{
868 register X *ptr = qobject_cast<X *>(src.data());
869 return QtSharedPointer::copyAndSetPointer(ptr, src);
870}
871template <class X, class T>
872Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src)
873{
874 return qSharedPointerObjectCast<X>(src.toStrongRef());
875}
876
877template <class X, class T>
878inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
879qobject_cast(const QSharedPointer<T> &src)
880{
881 return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
882}
883template <class X, class T>
884inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
885qobject_cast(const QWeakPointer<T> &src)
886{
887 return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
888}
889#endif
890
891
892template<typename T> Q_DECLARE_TYPEINFO_BODY(QWeakPointer<T>, Q_MOVABLE_TYPE);
893template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedPointer<T>, Q_MOVABLE_TYPE);
894
895
896QT_END_NAMESPACE
897
898QT_END_HEADER
899
900#endif
901