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) |
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 | }; |
63 | |
64 | template <typename T> |
65 | struct QScopedPointerArrayDeleter |
66 | { |
67 | static inline void cleanup(T *pointer) |
68 | { |
69 | // Enforce a complete type. |
70 | // If you get a compile error here, read the section on forward declared |
71 | // classes in the QScopedPointer documentation. |
72 | typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; |
73 | (void) sizeof(IsIncompleteType); |
74 | |
75 | delete [] pointer; |
76 | } |
77 | }; |
78 | |
79 | struct QScopedPointerPodDeleter |
80 | { |
81 | static inline void cleanup(void *pointer) { if (pointer) free(pointer); } |
82 | }; |
83 | |
84 | #ifndef QT_NO_QOBJECT |
85 | template <typename T> |
86 | struct QScopedPointerObjectDeleteLater |
87 | { |
88 | static inline void cleanup(T *pointer) { if (pointer) pointer->deleteLater(); } |
89 | }; |
90 | |
91 | class QObject; |
92 | typedef QScopedPointerObjectDeleteLater<QObject> QScopedPointerDeleteLater; |
93 | #endif |
94 | |
95 | template <typename T, typename Cleanup = QScopedPointerDeleter<T> > |
96 | class QScopedPointer |
97 | { |
98 | typedef T *QScopedPointer:: *RestrictedBool; |
99 | public: |
100 | explicit QScopedPointer(T *p = nullptr) noexcept : d(p) |
101 | { |
102 | } |
103 | |
104 | inline ~QScopedPointer() |
105 | { |
106 | T *oldD = this->d; |
107 | Cleanup::cleanup(oldD); |
108 | } |
109 | |
110 | inline T &operator*() const |
111 | { |
112 | Q_ASSERT(d); |
113 | return *d; |
114 | } |
115 | |
116 | T *operator->() const noexcept |
117 | { |
118 | return d; |
119 | } |
120 | |
121 | bool operator!() const noexcept |
122 | { |
123 | return !d; |
124 | } |
125 | |
126 | #if defined(Q_QDOC) |
127 | inline operator bool() const |
128 | { |
129 | return isNull() ? nullptr : &QScopedPointer::d; |
130 | } |
131 | #else |
132 | operator RestrictedBool() const noexcept |
133 | { |
134 | return isNull() ? nullptr : &QScopedPointer::d; |
135 | } |
136 | #endif |
137 | |
138 | T *data() const noexcept |
139 | { |
140 | return d; |
141 | } |
142 | |
143 | T *get() const noexcept |
144 | { |
145 | return d; |
146 | } |
147 | |
148 | bool isNull() const noexcept |
149 | { |
150 | return !d; |
151 | } |
152 | |
153 | void reset(T *other = nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval<T *>()))) |
154 | { |
155 | if (d == other) |
156 | return; |
157 | T *oldD = d; |
158 | d = other; |
159 | Cleanup::cleanup(oldD); |
160 | } |
161 | |
162 | T *take() noexcept |
163 | { |
164 | T *oldD = d; |
165 | d = nullptr; |
166 | return oldD; |
167 | } |
168 | |
169 | void swap(QScopedPointer<T, Cleanup> &other) noexcept |
170 | { |
171 | qSwap(d, other.d); |
172 | } |
173 | |
174 | typedef T *pointer; |
175 | |
176 | protected: |
177 | T *d; |
178 | |
179 | private: |
180 | Q_DISABLE_COPY(QScopedPointer) |
181 | }; |
182 | |
183 | template <class T, class Cleanup> |
184 | inline bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept |
185 | { |
186 | return lhs.data() == rhs.data(); |
187 | } |
188 | |
189 | template <class T, class Cleanup> |
190 | inline bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept |
191 | { |
192 | return lhs.data() != rhs.data(); |
193 | } |
194 | |
195 | template <class T, class Cleanup> |
196 | inline bool operator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept |
197 | { |
198 | return lhs.isNull(); |
199 | } |
200 | |
201 | template <class T, class Cleanup> |
202 | inline bool operator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept |
203 | { |
204 | return rhs.isNull(); |
205 | } |
206 | |
207 | template <class T, class Cleanup> |
208 | inline bool operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept |
209 | { |
210 | return !lhs.isNull(); |
211 | } |
212 | |
213 | template <class T, class Cleanup> |
214 | inline bool operator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept |
215 | { |
216 | return !rhs.isNull(); |
217 | } |
218 | |
219 | template <class T, class Cleanup> |
220 | inline void swap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2) noexcept |
221 | { p1.swap(p2); } |
222 | |
223 | template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> > |
224 | class QScopedArrayPointer : public QScopedPointer<T, Cleanup> |
225 | { |
226 | template <typename Ptr> |
227 | using if_same_type = typename std::enable_if<std::is_same<typename std::remove_cv<T>::type, Ptr>::value, bool>::type; |
228 | public: |
229 | inline QScopedArrayPointer() : QScopedPointer<T, Cleanup>(nullptr) {} |
230 | |
231 | template <typename D, if_same_type<D> = true> |
232 | explicit QScopedArrayPointer(D *p) |
233 | : QScopedPointer<T, Cleanup>(p) |
234 | { |
235 | } |
236 | |
237 | inline T &operator[](int i) |
238 | { |
239 | return this->d[i]; |
240 | } |
241 | |
242 | inline const T &operator[](int i) const |
243 | { |
244 | return this->d[i]; |
245 | } |
246 | |
247 | void swap(QScopedArrayPointer &other) noexcept // prevent QScopedPointer <->QScopedArrayPointer swaps |
248 | { QScopedPointer<T, Cleanup>::swap(other); } |
249 | |
250 | private: |
251 | explicit inline QScopedArrayPointer(void *) { |
252 | // Enforce the same type. |
253 | |
254 | // If you get a compile error here, make sure you declare |
255 | // QScopedArrayPointer with the same template type as you pass to the |
256 | // constructor. See also the QScopedPointer documentation. |
257 | |
258 | // Storing a scalar array as a pointer to a different type is not |
259 | // allowed and results in undefined behavior. |
260 | } |
261 | |
262 | Q_DISABLE_COPY(QScopedArrayPointer) |
263 | }; |
264 | |
265 | template <typename T, typename Cleanup> |
266 | inline void swap(QScopedArrayPointer<T, Cleanup> &lhs, QScopedArrayPointer<T, Cleanup> &rhs) noexcept |
267 | { lhs.swap(rhs); } |
268 | |
269 | QT_END_NAMESPACE |
270 | |
271 | #endif // QSCOPEDPOINTER_H |
272 | |