1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QPOINTER_H |
5 | #define QPOINTER_H |
6 | |
7 | #include <QtCore/qsharedpointer.h> |
8 | #include <QtCore/qtypeinfo.h> |
9 | |
10 | #ifndef QT_NO_QOBJECT |
11 | |
12 | QT_BEGIN_NAMESPACE |
13 | |
14 | class QVariant; |
15 | |
16 | template <class T> |
17 | class QPointer |
18 | { |
19 | static_assert(!std::is_pointer<T>::value, "QPointer's template type must not be a pointer type" ); |
20 | |
21 | template <typename X> |
22 | using if_convertible = std::enable_if_t<std::is_convertible_v<X*, T*>, bool>; |
23 | template <typename X> |
24 | friend class QPointer; |
25 | |
26 | using QObjectType = |
27 | typename std::conditional<std::is_const<T>::value, const QObject, QObject>::type; |
28 | QWeakPointer<QObjectType> wp; |
29 | public: |
30 | Q_NODISCARD_CTOR |
31 | QPointer() = default; |
32 | Q_NODISCARD_CTOR |
33 | inline QPointer(T *p) : wp(p, true) { } |
34 | // compiler-generated copy/move ctor/assignment operators are fine! |
35 | // compiler-generated dtor is fine! |
36 | |
37 | template <typename X, if_convertible<X> = true> |
38 | Q_NODISCARD_CTOR |
39 | QPointer(QPointer<X> &&other) noexcept |
40 | : wp(std::exchange(other.wp, nullptr).internalData(), true) {} |
41 | template <typename X, if_convertible<X> = true> |
42 | Q_NODISCARD_CTOR |
43 | QPointer(const QPointer<X> &other) noexcept |
44 | : wp(other.wp.internalData(), true) {} |
45 | |
46 | template <typename X, if_convertible<X> = true> |
47 | QPointer &operator=(const QPointer<X> &other) |
48 | { |
49 | wp.assign(other.data()); |
50 | return *this; |
51 | } |
52 | |
53 | #ifdef Q_QDOC |
54 | // Stop qdoc from complaining about missing function |
55 | ~QPointer(); |
56 | #endif |
57 | |
58 | inline void swap(QPointer &other) noexcept { wp.swap(other.wp); } |
59 | |
60 | inline QPointer<T> &operator=(T* p) |
61 | { wp.assign(static_cast<QObjectType*>(p)); return *this; } |
62 | |
63 | inline T* data() const |
64 | { return static_cast<T*>(wp.internalData()); } |
65 | inline T* get() const |
66 | { return data(); } |
67 | inline T* operator->() const |
68 | { return data(); } |
69 | inline T& operator*() const |
70 | { return *data(); } |
71 | inline operator T*() const |
72 | { return data(); } |
73 | |
74 | inline bool isNull() const |
75 | { return wp.isNull(); } |
76 | |
77 | inline void clear() |
78 | { wp.clear(); } |
79 | |
80 | #define DECLARE_COMPARE_SET(T1, A1, T2, A2) \ |
81 | friend bool operator==(T1, T2) \ |
82 | { return A1 == A2; } \ |
83 | friend bool operator!=(T1, T2) \ |
84 | { return A1 != A2; } |
85 | |
86 | #define DECLARE_TEMPLATE_COMPARE_SET(T1, A1, T2, A2) \ |
87 | template <typename X> \ |
88 | friend bool operator==(T1, T2) noexcept \ |
89 | { return A1 == A2; } \ |
90 | template <typename X> \ |
91 | friend bool operator!=(T1, T2) noexcept \ |
92 | { return A1 != A2; } |
93 | |
94 | DECLARE_TEMPLATE_COMPARE_SET(const QPointer &p1, p1.data(), const QPointer<X> &p2, p2.data()) |
95 | DECLARE_TEMPLATE_COMPARE_SET(const QPointer &p1, p1.data(), X *ptr, ptr) |
96 | DECLARE_TEMPLATE_COMPARE_SET(X *ptr, ptr, const QPointer &p2, p2.data()) |
97 | DECLARE_COMPARE_SET(const QPointer &p1, p1.data(), std::nullptr_t, nullptr) |
98 | DECLARE_COMPARE_SET(std::nullptr_t, nullptr, const QPointer &p2, p2.data()) |
99 | #undef DECLARE_COMPARE_SET |
100 | #undef DECLARE_TEMPLATE_COMPARE_SET |
101 | }; |
102 | template <class T> Q_DECLARE_TYPEINFO_BODY(QPointer<T>, Q_RELOCATABLE_TYPE); |
103 | |
104 | template<typename T> |
105 | QPointer<T> |
106 | qPointerFromVariant(const QVariant &variant) |
107 | { |
108 | const auto wp = QtSharedPointer::weakPointerFromVariant_internal(variant); |
109 | return QPointer<T>{qobject_cast<T*>(QtPrivate::EnableInternalData::internalData(p: wp))}; |
110 | } |
111 | |
112 | template <class T> |
113 | inline void swap(QPointer<T> &p1, QPointer<T> &p2) noexcept |
114 | { p1.swap(p2); } |
115 | |
116 | QT_END_NAMESPACE |
117 | |
118 | #endif // QT_NO_QOBJECT |
119 | |
120 | #endif // QPOINTER_H |
121 | |