File: | /home/gilles/Devel/8.x/core/libs/dimg/filters/hotpixels/hotpixelsweights.cpp |
Warning: | line 297, column 95 The left operand of '*' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* ============================================================ | ||||
2 | * | ||||
3 | * This file is a part of digiKam project | ||||
4 | * https://www.digikam.org | ||||
5 | * | ||||
6 | * Date : 2005-03-27 | ||||
7 | * Description : a class to calculate filter weights for hot pixels tool | ||||
8 | * | ||||
9 | * SPDX-FileCopyrightText: 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net> | ||||
10 | * SPDX-FileCopyrightText: 2005-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> | ||||
11 | * | ||||
12 | * SPDX-License-Identifier: GPL-2.0-or-later | ||||
13 | * | ||||
14 | * ============================================================ */ | ||||
15 | |||||
16 | #include "hotpixelsweights.h" | ||||
17 | |||||
18 | // C++ includes | ||||
19 | |||||
20 | #include <cstring> | ||||
21 | |||||
22 | // Qt includes | ||||
23 | |||||
24 | #include <QScopedArrayPointer> | ||||
25 | |||||
26 | namespace Digikam | ||||
27 | { | ||||
28 | |||||
29 | HotPixelsWeights::HotPixelsWeights(const HotPixelsWeights& w) | ||||
30 | { | ||||
31 | (*this) = w; | ||||
32 | } | ||||
33 | |||||
34 | HotPixelsWeights::~HotPixelsWeights() | ||||
35 | { | ||||
36 | if (!m_weightMatrices) | ||||
37 | { | ||||
38 | return; | ||||
39 | } | ||||
40 | |||||
41 | for (int i = 0 ; i < m_positions.count() ; ++i) | ||||
42 | { | ||||
43 | for (unsigned int j = 0 ; j < m_height ; ++j) | ||||
44 | { | ||||
45 | delete [] m_weightMatrices[i][j]; | ||||
46 | } | ||||
47 | } | ||||
48 | |||||
49 | delete [] m_weightMatrices; | ||||
50 | } | ||||
51 | |||||
52 | unsigned int HotPixelsWeights::height() const | ||||
53 | { | ||||
54 | return m_height; | ||||
55 | } | ||||
56 | |||||
57 | unsigned int HotPixelsWeights::polynomeOrder() const | ||||
58 | { | ||||
59 | return m_polynomeOrder; | ||||
60 | } | ||||
61 | |||||
62 | bool HotPixelsWeights::twoDim() const | ||||
63 | { | ||||
64 | return m_twoDim; | ||||
65 | } | ||||
66 | |||||
67 | unsigned int HotPixelsWeights::width() const | ||||
68 | { | ||||
69 | return m_width; | ||||
70 | } | ||||
71 | |||||
72 | void HotPixelsWeights::setHeight(int h) | ||||
73 | { | ||||
74 | m_height = h; | ||||
75 | } | ||||
76 | |||||
77 | void HotPixelsWeights::setPolynomeOrder(int order) | ||||
78 | { | ||||
79 | m_polynomeOrder = order; | ||||
80 | } | ||||
81 | |||||
82 | void HotPixelsWeights::setTwoDim(bool td) | ||||
83 | { | ||||
84 | m_twoDim = td; | ||||
85 | } | ||||
86 | |||||
87 | void HotPixelsWeights::setWidth(int w) | ||||
88 | { | ||||
89 | m_width = w; | ||||
90 | } | ||||
91 | |||||
92 | double** HotPixelsWeights::operator[](int n) const | ||||
93 | { | ||||
94 | return m_weightMatrices[n]; | ||||
95 | } | ||||
96 | |||||
97 | const QList<QPoint> HotPixelsWeights::positions() const | ||||
98 | { | ||||
99 | return m_positions; | ||||
100 | } | ||||
101 | |||||
102 | int HotPixelsWeights::coefficientNumber() const | ||||
103 | { | ||||
104 | return m_coefficientNumber; | ||||
105 | } | ||||
106 | |||||
107 | double** * HotPixelsWeights::weightMatrices() const | ||||
108 | { | ||||
109 | return m_weightMatrices; | ||||
110 | } | ||||
111 | |||||
112 | HotPixelsWeights& HotPixelsWeights::operator=(const HotPixelsWeights& w) | ||||
113 | { | ||||
114 | if (this == &w) | ||||
115 | { | ||||
116 | // we have to be sure that we are not self-assignment | ||||
117 | |||||
118 | return *this; | ||||
119 | } | ||||
120 | |||||
121 | m_height = w.height(); | ||||
122 | m_width = w.width(); | ||||
123 | m_positions = w.positions(); | ||||
124 | m_coefficientNumber = w.coefficientNumber(); | ||||
125 | m_twoDim = w.twoDim(); | ||||
126 | m_polynomeOrder = w.polynomeOrder(); | ||||
127 | |||||
128 | // Allocate memory and copy weights | ||||
129 | // if the original one was calculated | ||||
130 | |||||
131 | if (!w.weightMatrices()) | ||||
132 | { | ||||
133 | return *this; | ||||
134 | } | ||||
135 | else | ||||
136 | { | ||||
137 | double** * const origMatrices = w.weightMatrices(); | ||||
138 | |||||
139 | // Allocate m_positions.count() matrices | ||||
140 | |||||
141 | m_weightMatrices = new double** [m_positions.count()]; | ||||
142 | |||||
143 | for (int i = 0 ; i < m_positions.count() ; ++i) | ||||
144 | { | ||||
145 | // Allocate m_height rows on each position | ||||
146 | |||||
147 | m_weightMatrices[i] = new double* [m_height]; | ||||
148 | |||||
149 | for (uint j = 0 ; j < m_height ; ++j) | ||||
150 | { | ||||
151 | // Allocate m_width columns on each row | ||||
152 | |||||
153 | m_weightMatrices[i][j] = new double[m_width]; | ||||
154 | |||||
155 | for (uint k = 0 ; k < m_width ; ++k) | ||||
156 | { | ||||
157 | m_weightMatrices[i][j][k] = origMatrices[i][j][k]; | ||||
158 | } | ||||
159 | } | ||||
160 | } | ||||
161 | } | ||||
162 | |||||
163 | return *this; | ||||
164 | } | ||||
165 | |||||
166 | void HotPixelsWeights::calculateHotPixelsWeights() | ||||
167 | { | ||||
168 | m_coefficientNumber = (m_twoDim ? ((size_t)m_polynomeOrder + 1) * ((size_t)m_polynomeOrder + 1) | ||||
| |||||
169 | : (size_t)m_polynomeOrder + 1); | ||||
170 | size_t ix, iy, i, j; | ||||
171 | int x, y; | ||||
172 | |||||
173 | // Determine coordinates of pixels to be sampled | ||||
174 | |||||
175 | if (m_twoDim
| ||||
176 | { | ||||
177 | |||||
178 | int iPolynomeOrder = (int) m_polynomeOrder; // lets avoid signed/unsigned comparison warnings | ||||
179 | int iHeight = (int) height(); | ||||
180 | int iWidth = (int) width(); | ||||
181 | |||||
182 | for (y = (-1)*iPolynomeOrder ; (y < iHeight + iPolynomeOrder) ; ++y) | ||||
183 | { | ||||
184 | for (x = (-1)*iPolynomeOrder ; (x < iWidth + iPolynomeOrder) ; ++x) | ||||
185 | { | ||||
186 | if ( | ||||
187 | ((x < 0) && (y < 0) && (-x - y < iPolynomeOrder + 2)) || | ||||
188 | ((x < 0) && (y >= iHeight) && (-x + y - iHeight < iPolynomeOrder + 1)) || | ||||
189 | ((x >= iWidth) && (y < 0) && ( x - y - iWidth < iPolynomeOrder + 1)) || | ||||
190 | ((x >= iWidth) && (y >= iHeight) && ( x + y - iWidth - iHeight < iPolynomeOrder)) || | ||||
191 | ((x < 0) && (y >= 0) && (y < iHeight)) || ((x >= iWidth) && (y >= 0) && (y < iHeight)) || | ||||
192 | ((y < 0) && (x >= 0) && (x < iWidth)) || ((y >= iHeight) && (x >= 0) && (x < iWidth)) | ||||
193 | ) | ||||
194 | { | ||||
195 | QPoint position(x,y); | ||||
196 | m_positions.append(position); | ||||
197 | } | ||||
198 | } | ||||
199 | } | ||||
200 | } | ||||
201 | else | ||||
202 | { | ||||
203 | // In the one-dimensional case, only the y coordinate and y size is used. | ||||
204 | |||||
205 | // cppcheck-suppress signConversion | ||||
206 | for (y = (-1)*m_polynomeOrder ; y < 0 ; ++y) | ||||
207 | { | ||||
208 | QPoint position(0, y); | ||||
209 | m_positions.append(position); | ||||
210 | } | ||||
211 | |||||
212 | for (y = (int)height() ; (y < (int)height() + (int)m_polynomeOrder) ; ++y) | ||||
213 | { | ||||
214 | QPoint position(0, y); | ||||
215 | m_positions.append(position); | ||||
216 | } | ||||
217 | } | ||||
218 | |||||
219 | // Allocate memory. | ||||
220 | |||||
221 | QScopedArrayPointer<double> matrix (new double[m_coefficientNumber * m_coefficientNumber]{}); | ||||
222 | QScopedArrayPointer<double> vector0(new double[m_positions.count() * m_coefficientNumber]{}); | ||||
223 | QScopedArrayPointer<double> vector1(new double[m_positions.count() * m_coefficientNumber]{}); | ||||
224 | |||||
225 | // Calculate coefficient matrix and vectors | ||||
226 | |||||
227 | for (iy = 0 ; iy < m_coefficientNumber ; ++iy) | ||||
228 | { | ||||
229 | for (ix = 0 ; ix
| ||||
230 | { | ||||
231 | matrix[(int)(iy* m_coefficientNumber + ix)] = 0.0; | ||||
232 | } | ||||
233 | |||||
234 | for (j = 0 ; j < (size_t)m_positions.count() ; ++j) | ||||
235 | { | ||||
236 | vector0[(int)(iy * m_positions.count() + j)] = polyTerm(iy, m_positions.at((int)j).x(), | ||||
237 | m_positions.at((int)j).y(), m_polynomeOrder); | ||||
238 | |||||
239 | for (ix = 0 ; ix < m_coefficientNumber ; ++ix) | ||||
240 | { | ||||
241 | matrix[(int)(iy* m_coefficientNumber + ix)] += (vector0[(int)(iy * m_positions.count() + j)] * | ||||
242 | polyTerm(ix, m_positions.at((int)j).x(), m_positions.at((int)j).y(), m_polynomeOrder)); | ||||
243 | } | ||||
244 | } | ||||
245 | } | ||||
246 | |||||
247 | // Invert matrix. | ||||
248 | |||||
249 | matrixInv (matrix.data(), m_coefficientNumber); | ||||
250 | |||||
251 | // Multiply inverse matrix with vector. | ||||
252 | |||||
253 | for (iy = 0 ; iy < m_coefficientNumber ; ++iy) | ||||
254 | { | ||||
255 | for (j = 0 ; j < (size_t)m_positions.count() ; ++j) | ||||
256 | { | ||||
257 | vector1[(int)(iy * m_positions.count() + j)] = 0.0; | ||||
258 | |||||
259 | for (ix = 0 ; ix < m_coefficientNumber ; ++ix) | ||||
260 | { | ||||
261 | vector1[(int)(iy * m_positions.count() + j)] += matrix[(int)(iy * m_coefficientNumber + ix)] * | ||||
262 | vector0[(int)(ix * m_positions.count() + j)]; | ||||
263 | } | ||||
264 | } | ||||
265 | } | ||||
266 | |||||
267 | // Store weights | ||||
268 | |||||
269 | // Allocate m_positions.count() matrices. | ||||
270 | |||||
271 | m_weightMatrices = new double** [m_positions.count()]; | ||||
272 | |||||
273 | for (i = 0 ; i < (size_t)m_positions.count() ; ++i) | ||||
274 | { | ||||
275 | // Allocate m_height rows on each position | ||||
276 | |||||
277 | m_weightMatrices[i] = new double* [m_height]; | ||||
278 | |||||
279 | for (j = 0 ; j < m_height ; ++j) | ||||
280 | { | ||||
281 | // Allocate m_width columns on each row | ||||
282 | |||||
283 | m_weightMatrices[i][j] = new double[m_width]; | ||||
284 | } | ||||
285 | } | ||||
286 | |||||
287 | for (y = 0 ; y < (int)m_height ; ++y) | ||||
288 | { | ||||
289 | for (x = 0 ; x < (int)m_width ; ++x) | ||||
290 | { | ||||
291 | for (j = 0 ; j < (size_t)m_positions.count() ; ++j) | ||||
292 | { | ||||
293 | m_weightMatrices[j][y][x] = 0.0; | ||||
294 | |||||
295 | for (iy = 0 ; iy < m_coefficientNumber ; ++iy) | ||||
296 | { | ||||
297 | m_weightMatrices[j][y][x] += vector1[(int)(iy * m_positions.count() + j)] * | ||||
| |||||
298 | polyTerm(iy, x, y, m_polynomeOrder); | ||||
299 | } | ||||
300 | |||||
301 | m_weightMatrices[j][y][x] *= (double)m_positions.count(); | ||||
302 | } | ||||
303 | } | ||||
304 | } | ||||
305 | } | ||||
306 | |||||
307 | bool HotPixelsWeights::operator==(const HotPixelsWeights& ws) const | ||||
308 | { | ||||
309 | return ( | ||||
310 | (m_height == ws.height()) && | ||||
311 | (m_width == ws.width()) && | ||||
312 | (m_polynomeOrder == ws.polynomeOrder()) && | ||||
313 | (m_twoDim == ws.twoDim()) | ||||
314 | ); | ||||
315 | } | ||||
316 | |||||
317 | /** | ||||
318 | * Invert a quadratic matrix. | ||||
319 | */ | ||||
320 | void HotPixelsWeights::matrixInv (double* const a, const size_t size) | ||||
321 | { | ||||
322 | QScopedArrayPointer<double> b(new double[size * size]{}); | ||||
323 | size_t ix, iy, j; | ||||
324 | |||||
325 | // Copy matrix to new location. | ||||
326 | |||||
327 | memcpy(b.data(), a, sizeof (double) * size * size); | ||||
328 | |||||
329 | // Set destination matrix to unit matrix. | ||||
330 | |||||
331 | for (iy = 0 ; iy < size ; ++iy) | ||||
332 | { | ||||
333 | for (ix = 0 ; ix < size ; ++ix) | ||||
334 | { | ||||
335 | a[(int)(iy* size + ix)] = (ix == iy) ? 1.0 : 0.0; | ||||
336 | } | ||||
337 | } | ||||
338 | |||||
339 | // Convert matrix to upper triangle form. | ||||
340 | |||||
341 | for (iy = 0 ; iy < size - 1 ; ++iy) | ||||
342 | { | ||||
343 | for (j = iy + 1 ; j < size ; ++j) | ||||
344 | { | ||||
345 | const double factor = b[(int)(j * size + iy)] / b[(int)(iy * size + iy)]; | ||||
346 | |||||
347 | for (ix = 0 ; ix < size ; ++ix) | ||||
348 | { | ||||
349 | b[(int)(j* size + ix)] -= factor * b[(int)(iy * size + ix)]; | ||||
350 | a[(int)(j* size + ix)] -= factor * a[(int)(iy * size + ix)]; | ||||
351 | } | ||||
352 | } | ||||
353 | } | ||||
354 | |||||
355 | // Convert matrix to diagonal form. | ||||
356 | |||||
357 | for (iy = size - 1 ; iy > 0 ; --iy) | ||||
358 | { | ||||
359 | for (j = 0 ; j < iy ; ++j) | ||||
360 | { | ||||
361 | const double factor = b[(int)(j * size + iy)] / b[(int)(iy * size + iy)]; | ||||
362 | |||||
363 | for (ix = 0 ; ix < size ; ++ix) | ||||
364 | { | ||||
365 | a[(int)(j* size + ix)] -= factor * a[(int)(iy * size + ix)]; | ||||
366 | } | ||||
367 | } | ||||
368 | } | ||||
369 | |||||
370 | // Convert matrix to unit matrix. | ||||
371 | |||||
372 | for (iy = 0 ; iy < size ; ++iy) | ||||
373 | { | ||||
374 | for (ix = 0 ; ix < size ; ++ix) | ||||
375 | { | ||||
376 | a[(int)(iy* size + ix)] /= b[(int)(iy * size + iy)]; | ||||
377 | } | ||||
378 | } | ||||
379 | } | ||||
380 | |||||
381 | /** | ||||
382 | * Calculates one term of the polynomial | ||||
383 | */ | ||||
384 | double HotPixelsWeights::polyTerm (const size_t i_coeff, const int x, const int y, const int poly_order) const | ||||
385 | { | ||||
386 | const size_t x_power = i_coeff / ((size_t)poly_order + 1); | ||||
387 | const size_t y_power = i_coeff % ((size_t)poly_order + 1); | ||||
388 | int result = 1; | ||||
389 | size_t i; | ||||
390 | |||||
391 | for (i = 0 ; i < x_power ; ++i) | ||||
392 | { | ||||
393 | result *= x; | ||||
394 | } | ||||
395 | |||||
396 | for (i = 0 ; i < y_power ; ++i) | ||||
397 | { | ||||
398 | result *= y; | ||||
399 | } | ||||
400 | |||||
401 | return (double)result; | ||||
402 | } | ||||
403 | |||||
404 | } // namespace Digikam |
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 QSCOPEDPOINTER_H |
5 | #define QSCOPEDPOINTER_H |
6 | |
7 | #include <QtCore/qglobal.h> |
8 | |
9 | #include <stdlib.h> |
10 | |
11 | QT_BEGIN_NAMESPACE |
12 | |
13 | template <typename T> |
14 | struct QScopedPointerDeleter |
15 | { |
16 | static inline void cleanup(T *pointer) noexcept |
17 | { |
18 | // Enforce a complete type. |
19 | // If you get a compile error here, read the section on forward declared |
20 | // classes in the QScopedPointer documentation. |
21 | typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; |
22 | (void) sizeof(IsIncompleteType); |
23 | |
24 | delete pointer; |
25 | } |
26 | void operator()(T *pointer) const noexcept |
27 | { |
28 | cleanup(pointer); |
29 | } |
30 | }; |
31 | |
32 | template <typename T> |
33 | struct QScopedPointerArrayDeleter |
34 | { |
35 | static inline void cleanup(T *pointer) noexcept |
36 | { |
37 | // Enforce a complete type. |
38 | // If you get a compile error here, read the section on forward declared |
39 | // classes in the QScopedPointer documentation. |
40 | typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; |
41 | (void) sizeof(IsIncompleteType); |
42 | |
43 | delete[] pointer; |
44 | } |
45 | void operator()(T *pointer) const noexcept |
46 | { |
47 | cleanup(pointer); |
48 | } |
49 | }; |
50 | |
51 | struct QScopedPointerPodDeleter |
52 | { |
53 | static inline void cleanup(void *pointer) noexcept { free(pointer); } |
54 | void operator()(void *pointer) const noexcept { cleanup(pointer); } |
55 | }; |
56 | |
57 | #ifndef QT_NO_QOBJECT |
58 | template <typename T> |
59 | struct QScopedPointerObjectDeleteLater |
60 | { |
61 | static inline void cleanup(T *pointer) { if (pointer) pointer->deleteLater(); } |
62 | void operator()(T *pointer) const { cleanup(pointer); } |
63 | }; |
64 | |
65 | class QObject; |
66 | typedef QScopedPointerObjectDeleteLater<QObject> QScopedPointerDeleteLater; |
67 | #endif |
68 | |
69 | template <typename T, typename Cleanup = QScopedPointerDeleter<T> > |
70 | class QScopedPointer |
71 | { |
72 | public: |
73 | Q_NODISCARD_CTOR[[nodiscard]] |
74 | explicit QScopedPointer(T *p = nullptr) noexcept : d(p) |
75 | { |
76 | } |
77 | |
78 | inline ~QScopedPointer() |
79 | { |
80 | T *oldD = this->d; |
81 | Cleanup::cleanup(oldD); |
82 | } |
83 | |
84 | inline T &operator*() const |
85 | { |
86 | Q_ASSERT(d)((d) ? static_cast<void>(0) : qt_assert("d", "/opt/qt6/include/QtCore/qscopedpointer.h" , 86)); |
87 | return *d; |
88 | } |
89 | |
90 | T *operator->() const noexcept |
91 | { |
92 | return d; |
93 | } |
94 | |
95 | bool operator!() const noexcept |
96 | { |
97 | return !d; |
98 | } |
99 | |
100 | explicit operator bool() const |
101 | { |
102 | return !isNull(); |
103 | } |
104 | |
105 | T *data() const noexcept |
106 | { |
107 | return d; |
108 | } |
109 | |
110 | T *get() const noexcept |
111 | { |
112 | return d; |
113 | } |
114 | |
115 | bool isNull() const noexcept |
116 | { |
117 | return !d; |
118 | } |
119 | |
120 | void reset(T *other = nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval<T *>()))) |
121 | { |
122 | if (d == other) |
123 | return; |
124 | T *oldD = std::exchange(d, other); |
125 | Cleanup::cleanup(oldD); |
126 | } |
127 | |
128 | #if QT_DEPRECATED_SINCE(6, 1)(((6<<16)|(1<<8)|(0)) > 0x050E00) |
129 | QT_DEPRECATED_VERSION_X_6_1("Use std::unique_ptr instead, and call release().") |
130 | T *take() noexcept |
131 | { |
132 | T *oldD = std::exchange(d, nullptr); |
133 | return oldD; |
134 | } |
135 | #endif |
136 | |
137 | #if QT_DEPRECATED_SINCE(6, 2)(((6<<16)|(2<<8)|(0)) > 0x050E00) |
138 | QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedPointer.") |
139 | void swap(QScopedPointer<T, Cleanup> &other) noexcept |
140 | { |
141 | qt_ptr_swap(d, other.d); |
142 | } |
143 | #endif |
144 | |
145 | typedef T *pointer; |
146 | |
147 | friend bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept |
148 | { |
149 | return lhs.data() == rhs.data(); |
150 | } |
151 | |
152 | friend bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept |
153 | { |
154 | return lhs.data() != rhs.data(); |
155 | } |
156 | |
157 | friend bool operator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept |
158 | { |
159 | return lhs.isNull(); |
160 | } |
161 | |
162 | friend bool operator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept |
163 | { |
164 | return rhs.isNull(); |
165 | } |
166 | |
167 | friend bool operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept |
168 | { |
169 | return !lhs.isNull(); |
170 | } |
171 | |
172 | friend bool operator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept |
173 | { |
174 | return !rhs.isNull(); |
175 | } |
176 | |
177 | #if QT_DEPRECATED_SINCE(6, 2)(((6<<16)|(2<<8)|(0)) > 0x050E00) |
178 | QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedPointer.") |
179 | friend void swap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2) noexcept |
180 | { p1.swap(p2); } |
181 | #endif |
182 | |
183 | protected: |
184 | T *d; |
185 | |
186 | private: |
187 | Q_DISABLE_COPY_MOVE(QScopedPointer)QScopedPointer(const QScopedPointer &) = delete; QScopedPointer &operator=(const QScopedPointer &) = delete; QScopedPointer (QScopedPointer &&) = delete; QScopedPointer &operator =(QScopedPointer &&) = delete; |
188 | }; |
189 | |
190 | template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> > |
191 | class QScopedArrayPointer : public QScopedPointer<T, Cleanup> |
192 | { |
193 | template <typename Ptr> |
194 | using if_same_type = typename std::enable_if<std::is_same<typename std::remove_cv<T>::type, Ptr>::value, bool>::type; |
195 | public: |
196 | Q_NODISCARD_CTOR[[nodiscard]] |
197 | inline QScopedArrayPointer() : QScopedPointer<T, Cleanup>(nullptr) {} |
198 | inline ~QScopedArrayPointer() = default; |
199 | |
200 | template <typename D, if_same_type<D> = true> |
201 | Q_NODISCARD_CTOR[[nodiscard]] |
202 | explicit QScopedArrayPointer(D *p) |
203 | : QScopedPointer<T, Cleanup>(p) |
204 | { |
205 | } |
206 | |
207 | T &operator[](qsizetype i) |
208 | { |
209 | return this->d[i]; |
210 | } |
211 | |
212 | const T &operator[](qsizetype i) const |
213 | { |
214 | return this->d[i]; |
215 | } |
216 | |
217 | #if QT_DEPRECATED_SINCE(6, 2)(((6<<16)|(2<<8)|(0)) > 0x050E00) |
218 | QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedArrayPointer.") |
219 | void swap(QScopedArrayPointer &other) noexcept // prevent QScopedPointer <->QScopedArrayPointer swaps |
220 | { QScopedPointer<T, Cleanup>::swap(other); } |
221 | #endif |
222 | |
223 | private: |
224 | explicit inline QScopedArrayPointer(void *) |
225 | { |
226 | // Enforce the same type. |
227 | |
228 | // If you get a compile error here, make sure you declare |
229 | // QScopedArrayPointer with the same template type as you pass to the |
230 | // constructor. See also the QScopedPointer documentation. |
231 | |
232 | // Storing a scalar array as a pointer to a different type is not |
233 | // allowed and results in undefined behavior. |
234 | } |
235 | |
236 | Q_DISABLE_COPY_MOVE(QScopedArrayPointer)QScopedArrayPointer(const QScopedArrayPointer &) = delete ; QScopedArrayPointer &operator=(const QScopedArrayPointer &) = delete; QScopedArrayPointer(QScopedArrayPointer && ) = delete; QScopedArrayPointer &operator=(QScopedArrayPointer &&) = delete; |
237 | }; |
238 | |
239 | #if QT_DEPRECATED_SINCE(6, 2)(((6<<16)|(2<<8)|(0)) > 0x050E00) |
240 | template <typename T, typename Cleanup> |
241 | QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedArrayPointer.") |
242 | inline void swap(QScopedArrayPointer<T, Cleanup> &lhs, QScopedArrayPointer<T, Cleanup> &rhs) noexcept |
243 | { lhs.swap(rhs); } |
244 | #endif |
245 | |
246 | QT_END_NAMESPACE |
247 | |
248 | #endif // QSCOPEDPOINTER_H |