1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
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 The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/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 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #ifndef QSCOPEDPOINTER_H |
41 | #define QSCOPEDPOINTER_H |
42 | |
43 | #include <QtCore/qglobal.h> |
44 | |
45 | #include <stdlib.h> |
46 | |
47 | QT_BEGIN_NAMESPACE |
48 | |
49 | template <typename T> |
50 | struct QScopedPointerDeleter |
51 | { |
52 | static inline void cleanup(T *pointer) noexcept |
53 | { |
54 | // Enforce a complete type. |
55 | // If you get a compile error here, read the section on forward declared |
56 | // classes in the QScopedPointer documentation. |
57 | typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; |
58 | (void) sizeof(IsIncompleteType); |
59 | |
60 | delete pointer; |
61 | } |
62 | void operator()(T *pointer) const noexcept |
63 | { |
64 | cleanup(pointer); |
65 | } |
66 | }; |
67 | |
68 | template <typename T> |
69 | struct QScopedPointerArrayDeleter |
70 | { |
71 | static inline void cleanup(T *pointer) noexcept |
72 | { |
73 | // Enforce a complete type. |
74 | // If you get a compile error here, read the section on forward declared |
75 | // classes in the QScopedPointer documentation. |
76 | typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; |
77 | (void) sizeof(IsIncompleteType); |
78 | |
79 | delete[] pointer; |
80 | } |
81 | void operator()(T *pointer) const noexcept |
82 | { |
83 | cleanup(pointer); |
84 | } |
85 | }; |
86 | |
87 | struct QScopedPointerPodDeleter |
88 | { |
89 | static inline void cleanup(void *pointer) noexcept { free(pointer); } |
90 | void operator()(void *pointer) const noexcept { cleanup(pointer); } |
91 | }; |
92 | |
93 | #ifndef QT_NO_QOBJECT |
94 | template <typename T> |
95 | struct QScopedPointerObjectDeleteLater |
96 | { |
97 | static inline void cleanup(T *pointer) { if (pointer) pointer->deleteLater(); } |
98 | void operator()(T *pointer) const { cleanup(pointer); } |
99 | }; |
100 | |
101 | class QObject; |
102 | typedef QScopedPointerObjectDeleteLater<QObject> QScopedPointerDeleteLater; |
103 | #endif |
104 | |
105 | template <typename T, typename Cleanup = QScopedPointerDeleter<T> > |
106 | class QScopedPointer |
107 | { |
108 | public: |
109 | explicit QScopedPointer(T *p = nullptr) noexcept : d(p) |
110 | { |
111 | } |
112 | |
113 | inline ~QScopedPointer() |
114 | { |
115 | T *oldD = this->d; |
116 | Cleanup::cleanup(oldD); |
117 | } |
118 | |
119 | inline T &operator*() const |
120 | { |
121 | Q_ASSERT(d); |
122 | return *d; |
123 | } |
124 | |
125 | T *operator->() const noexcept |
126 | { |
127 | return d; |
128 | } |
129 | |
130 | bool operator!() const noexcept |
131 | { |
132 | return !d; |
133 | } |
134 | |
135 | explicit operator bool() const |
136 | { |
137 | return !isNull(); |
138 | } |
139 | |
140 | T *data() const noexcept |
141 | { |
142 | return d; |
143 | } |
144 | |
145 | T *get() const noexcept |
146 | { |
147 | return d; |
148 | } |
149 | |
150 | bool isNull() const noexcept |
151 | { |
152 | return !d; |
153 | } |
154 | |
155 | void reset(T *other = nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval<T *>()))) |
156 | { |
157 | if (d == other) |
158 | return; |
159 | T *oldD = qExchange(d, other); |
160 | Cleanup::cleanup(oldD); |
161 | } |
162 | |
163 | #if QT_DEPRECATED_SINCE(6, 1) |
164 | QT_DEPRECATED_VERSION_X_6_1("Use std::unique_ptr instead, and call release()." ) |
165 | T *take() noexcept |
166 | { |
167 | T *oldD = qExchange(d, nullptr); |
168 | return oldD; |
169 | } |
170 | #endif |
171 | |
172 | #if QT_DEPRECATED_SINCE(6, 2) |
173 | QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedPointer." ) |
174 | void swap(QScopedPointer<T, Cleanup> &other) noexcept |
175 | { |
176 | qSwap(d, other.d); |
177 | } |
178 | #endif |
179 | |
180 | typedef T *pointer; |
181 | |
182 | friend bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept |
183 | { |
184 | return lhs.data() == rhs.data(); |
185 | } |
186 | |
187 | friend bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept |
188 | { |
189 | return lhs.data() != rhs.data(); |
190 | } |
191 | |
192 | friend bool operator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept |
193 | { |
194 | return lhs.isNull(); |
195 | } |
196 | |
197 | friend bool operator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept |
198 | { |
199 | return rhs.isNull(); |
200 | } |
201 | |
202 | friend bool operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept |
203 | { |
204 | return !lhs.isNull(); |
205 | } |
206 | |
207 | friend bool operator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept |
208 | { |
209 | return !rhs.isNull(); |
210 | } |
211 | |
212 | #if QT_DEPRECATED_SINCE(6, 2) |
213 | QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedPointer." ) |
214 | friend void swap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2) noexcept |
215 | { p1.swap(p2); } |
216 | #endif |
217 | |
218 | protected: |
219 | T *d; |
220 | |
221 | private: |
222 | Q_DISABLE_COPY(QScopedPointer) |
223 | }; |
224 | |
225 | template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> > |
226 | class QScopedArrayPointer : public QScopedPointer<T, Cleanup> |
227 | { |
228 | template <typename Ptr> |
229 | using if_same_type = typename std::enable_if<std::is_same<typename std::remove_cv<T>::type, Ptr>::value, bool>::type; |
230 | public: |
231 | inline QScopedArrayPointer() : QScopedPointer<T, Cleanup>(nullptr) {} |
232 | |
233 | template <typename D, if_same_type<D> = true> |
234 | explicit QScopedArrayPointer(D *p) |
235 | : QScopedPointer<T, Cleanup>(p) |
236 | { |
237 | } |
238 | |
239 | inline T &operator[](int i) |
240 | { |
241 | return this->d[i]; |
242 | } |
243 | |
244 | inline const T &operator[](int i) const |
245 | { |
246 | return this->d[i]; |
247 | } |
248 | |
249 | #if QT_DEPRECATED_SINCE(6, 2) |
250 | QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedArrayPointer." ) |
251 | void swap(QScopedArrayPointer &other) noexcept // prevent QScopedPointer <->QScopedArrayPointer swaps |
252 | { QScopedPointer<T, Cleanup>::swap(other); } |
253 | #endif |
254 | |
255 | private: |
256 | explicit inline QScopedArrayPointer(void *) |
257 | { |
258 | // Enforce the same type. |
259 | |
260 | // If you get a compile error here, make sure you declare |
261 | // QScopedArrayPointer with the same template type as you pass to the |
262 | // constructor. See also the QScopedPointer documentation. |
263 | |
264 | // Storing a scalar array as a pointer to a different type is not |
265 | // allowed and results in undefined behavior. |
266 | } |
267 | |
268 | Q_DISABLE_COPY(QScopedArrayPointer) |
269 | }; |
270 | |
271 | #if QT_DEPRECATED_SINCE(6, 2) |
272 | template <typename T, typename Cleanup> |
273 | QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedArrayPointer." ) |
274 | inline void swap(QScopedArrayPointer<T, Cleanup> &lhs, QScopedArrayPointer<T, Cleanup> &rhs) noexcept |
275 | { lhs.swap(rhs); } |
276 | #endif |
277 | |
278 | QT_END_NAMESPACE |
279 | |
280 | #endif // QSCOPEDPOINTER_H |
281 | |