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() noexcept = default; |
32 | Q_NODISCARD_CTOR |
33 | constexpr QPointer(std::nullptr_t) noexcept : QPointer{} {} |
34 | Q_WEAK_OVERLOAD |
35 | Q_NODISCARD_CTOR |
36 | inline QPointer(T *p) : wp(p, true) { } |
37 | // compiler-generated copy/move ctor/assignment operators are fine! |
38 | // compiler-generated dtor is fine! |
39 | |
40 | template <typename X, if_convertible<X> = true> |
41 | Q_NODISCARD_CTOR |
42 | QPointer(QPointer<X> &&other) noexcept |
43 | : wp(std::exchange(other.wp, nullptr).internalData(), true) {} |
44 | template <typename X, if_convertible<X> = true> |
45 | Q_NODISCARD_CTOR |
46 | QPointer(const QPointer<X> &other) noexcept |
47 | : wp(other.wp.internalData(), true) {} |
48 | |
49 | template <typename X, if_convertible<X> = true> |
50 | QPointer &operator=(const QPointer<X> &other) noexcept |
51 | { |
52 | QPointer(other).swap(*this); |
53 | return *this; |
54 | } |
55 | |
56 | template <typename X, if_convertible<X> = true> |
57 | QPointer &operator=(QPointer<X> &&other) noexcept |
58 | { |
59 | QPointer(std::move(other)).swap(*this); |
60 | return *this; |
61 | } |
62 | |
63 | #ifdef Q_QDOC |
64 | // Stop qdoc from complaining about missing function |
65 | ~QPointer(); |
66 | #endif |
67 | |
68 | inline void swap(QPointer &other) noexcept { wp.swap(other.wp); } |
69 | |
70 | inline QPointer<T> &operator=(T* p) |
71 | { wp.assign(static_cast<QObjectType*>(p)); return *this; } |
72 | |
73 | T* data() const noexcept |
74 | { return static_cast<T*>(wp.internalData()); } |
75 | T* get() const noexcept |
76 | { return data(); } |
77 | T* operator->() const noexcept |
78 | { return data(); } |
79 | T& operator*() const noexcept |
80 | { return *data(); } |
81 | operator T*() const noexcept |
82 | { return data(); } |
83 | |
84 | bool isNull() const noexcept |
85 | { return wp.isNull(); } |
86 | |
87 | void clear() noexcept |
88 | { wp.clear(); } |
89 | |
90 | friend void swap(QPointer &lhs, QPointer &rhs) noexcept |
91 | { lhs.swap(rhs); } |
92 | |
93 | #define DECLARE_COMPARE_SET(T1, A1, T2, A2) \ |
94 | friend bool operator==(T1, T2) noexcept \ |
95 | { return A1 == A2; } \ |
96 | friend bool operator!=(T1, T2) noexcept \ |
97 | { return A1 != A2; } |
98 | |
99 | #define DECLARE_TEMPLATE_COMPARE_SET(T1, A1, T2, A2) \ |
100 | template <typename X> \ |
101 | friend bool operator==(T1, T2) noexcept \ |
102 | { return A1 == A2; } \ |
103 | template <typename X> \ |
104 | friend bool operator!=(T1, T2) noexcept \ |
105 | { return A1 != A2; } |
106 | |
107 | DECLARE_TEMPLATE_COMPARE_SET(const QPointer &p1, p1.data(), const QPointer<X> &p2, p2.data()) |
108 | DECLARE_TEMPLATE_COMPARE_SET(const QPointer &p1, p1.data(), X *ptr, ptr) |
109 | DECLARE_TEMPLATE_COMPARE_SET(X *ptr, ptr, const QPointer &p2, p2.data()) |
110 | DECLARE_COMPARE_SET(const QPointer &p1, p1.data(), std::nullptr_t, nullptr) |
111 | DECLARE_COMPARE_SET(std::nullptr_t, nullptr, const QPointer &p2, p2.data()) |
112 | #undef DECLARE_COMPARE_SET |
113 | #undef DECLARE_TEMPLATE_COMPARE_SET |
114 | }; |
115 | template <class T> Q_DECLARE_TYPEINFO_BODY(QPointer<T>, Q_RELOCATABLE_TYPE); |
116 | |
117 | template<typename T> |
118 | QPointer<T> |
119 | qPointerFromVariant(const QVariant &variant) |
120 | { |
121 | const auto wp = QtSharedPointer::weakPointerFromVariant_internal(variant); |
122 | return QPointer<T>{qobject_cast<T*>(QtPrivate::EnableInternalData::internalData(p: wp))}; |
123 | } |
124 | |
125 | QT_END_NAMESPACE |
126 | |
127 | #endif // QT_NO_QOBJECT |
128 | |
129 | #endif // QPOINTER_H |
130 | |