1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 // <memory>
10
11 // unique_ptr
12
13 // Example move-only deleter
14
15 #ifndef SUPPORT_DELETER_TYPES_H
16 #define SUPPORT_DELETER_TYPES_H
17
18 #include <cstddef>
19 #include <type_traits>
20 #include <utility>
21 #include <cassert>
22
23 #include "test_macros.h"
24 #include "min_allocator.h"
25
26 #if TEST_STD_VER >= 11
27
28 template <class T>
29 class Deleter {
30 int state_;
31
32 Deleter(const Deleter&);
33 Deleter& operator=(const Deleter&);
34
35 public:
Deleter(Deleter && r)36 TEST_CONSTEXPR_CXX23 Deleter(Deleter&& r) : state_(r.state_) { r.state_ = 0; }
37 TEST_CONSTEXPR_CXX23 Deleter& operator=(Deleter&& r) {
38 state_ = r.state_;
39 r.state_ = 0;
40 return *this;
41 }
42
Deleter()43 TEST_CONSTEXPR_CXX23 Deleter() : state_(0) {}
Deleter(int s)44 TEST_CONSTEXPR_CXX23 explicit Deleter(int s) : state_(s) {}
~Deleter()45 TEST_CONSTEXPR_CXX23 ~Deleter() {
46 assert(state_ >= 0);
47 state_ = -1;
48 }
49
50 template <class U>
51 TEST_CONSTEXPR_CXX23 Deleter(Deleter<U>&& d, typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
52 : state_(d.state()) {
53 d.set_state(0);
54 }
55
56 private:
57 template <class U>
58 Deleter(const Deleter<U>& d, typename std::enable_if<!std::is_same<U, T>::value>::type* = 0);
59
60 public:
state()61 TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)62 TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
63
operator()64 TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete p; }
65 };
66
67 template <class T>
68 class Deleter<T[]> {
69 int state_;
70
71 Deleter(const Deleter&);
72 Deleter& operator=(const Deleter&);
73
74 public:
Deleter(Deleter && r)75 TEST_CONSTEXPR_CXX23 Deleter(Deleter&& r) : state_(r.state_) { r.state_ = 0; }
76 TEST_CONSTEXPR_CXX23 Deleter& operator=(Deleter&& r) {
77 state_ = r.state_;
78 r.state_ = 0;
79 return *this;
80 }
81
Deleter()82 TEST_CONSTEXPR_CXX23 Deleter() : state_(0) {}
Deleter(int s)83 TEST_CONSTEXPR_CXX23 explicit Deleter(int s) : state_(s) {}
~Deleter()84 TEST_CONSTEXPR_CXX23 ~Deleter() {
85 assert(state_ >= 0);
86 state_ = -1;
87 }
88
state()89 TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)90 TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
91
operator()92 TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete[] p; }
93 };
94
95 #else // TEST_STD_VER < 11
96
97 template <class T>
98 class Deleter {
99 mutable int state_;
100
101 public:
Deleter()102 Deleter() : state_(0) {}
Deleter(int s)103 explicit Deleter(int s) : state_(s) {}
104
Deleter(Deleter const & other)105 Deleter(Deleter const& other) : state_(other.state_) { other.state_ = 0; }
106 Deleter& operator=(Deleter const& other) {
107 state_ = other.state_;
108 other.state_ = 0;
109 return *this;
110 }
111
~Deleter()112 ~Deleter() {
113 assert(state_ >= 0);
114 state_ = -1;
115 }
116
117 template <class U>
118 Deleter(Deleter<U> d, typename std::enable_if<!std::is_same<U, T>::value>::type* = 0) : state_(d.state()) {}
119
120 public:
state()121 int state() const { return state_; }
set_state(int i)122 void set_state(int i) { state_ = i; }
123
operator()124 void operator()(T* p) { delete p; }
125 };
126
127 template <class T>
128 class Deleter<T[]> {
129 mutable int state_;
130
131 public:
Deleter(Deleter const & other)132 Deleter(Deleter const& other) : state_(other.state_) { other.state_ = 0; }
133 Deleter& operator=(Deleter const& other) {
134 state_ = other.state_;
135 other.state_ = 0;
136 return *this;
137 }
138
Deleter()139 Deleter() : state_(0) {}
Deleter(int s)140 explicit Deleter(int s) : state_(s) {}
~Deleter()141 ~Deleter() {
142 assert(state_ >= 0);
143 state_ = -1;
144 }
145
state()146 int state() const { return state_; }
set_state(int i)147 void set_state(int i) { state_ = i; }
148
operator()149 void operator()(T* p) { delete[] p; }
150 };
151
152 #endif
153
154 template <class T>
swap(Deleter<T> & x,Deleter<T> & y)155 TEST_CONSTEXPR_CXX23 void swap(Deleter<T>& x, Deleter<T>& y) {
156 Deleter<T> t(std::move(x));
157 x = std::move(y);
158 y = std::move(t);
159 }
160
161 template <class T>
162 class CDeleter {
163 int state_;
164
165 public:
CDeleter()166 TEST_CONSTEXPR_CXX23 CDeleter() : state_(0) {}
CDeleter(int s)167 TEST_CONSTEXPR_CXX23 explicit CDeleter(int s) : state_(s) {}
168 TEST_CONSTEXPR_CXX23 CDeleter(const CDeleter&) = default;
169 TEST_CONSTEXPR_CXX23 CDeleter& operator=(const CDeleter&) = default;
~CDeleter()170 TEST_CONSTEXPR_CXX23 ~CDeleter() {
171 assert(state_ >= 0);
172 state_ = -1;
173 }
174
175 template <class U>
CDeleter(const CDeleter<U> & d)176 TEST_CONSTEXPR_CXX23 CDeleter(const CDeleter<U>& d) : state_(d.state()) {}
177
state()178 TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)179 TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
180
operator()181 TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete p; }
182 };
183
184 template <class T>
185 class CDeleter<T[]> {
186 int state_;
187
188 public:
CDeleter()189 TEST_CONSTEXPR_CXX23 CDeleter() : state_(0) {}
CDeleter(int s)190 TEST_CONSTEXPR_CXX23 explicit CDeleter(int s) : state_(s) {}
191 template <class U>
CDeleter(const CDeleter<U> & d)192 TEST_CONSTEXPR_CXX23 CDeleter(const CDeleter<U>& d) : state_(d.state()) {}
193 TEST_CONSTEXPR_CXX23 CDeleter(const CDeleter&) = default;
194 TEST_CONSTEXPR_CXX23 CDeleter& operator=(const CDeleter&) = default;
~CDeleter()195 TEST_CONSTEXPR_CXX23 ~CDeleter() {
196 assert(state_ >= 0);
197 state_ = -1;
198 }
199
state()200 TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)201 TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
202
operator()203 TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete[] p; }
204 };
205
206 template <class T>
swap(CDeleter<T> & x,CDeleter<T> & y)207 TEST_CONSTEXPR_CXX23 void swap(CDeleter<T>& x, CDeleter<T>& y) {
208 CDeleter<T> t(std::move(x));
209 x = std::move(y);
210 y = std::move(t);
211 }
212
213 // Non-copyable deleter
214 template <class T>
215 class NCDeleter {
216 int state_;
217 NCDeleter(NCDeleter const&);
218 NCDeleter& operator=(NCDeleter const&);
219
220 public:
NCDeleter()221 TEST_CONSTEXPR_CXX23 NCDeleter() : state_(0) {}
NCDeleter(int s)222 TEST_CONSTEXPR_CXX23 explicit NCDeleter(int s) : state_(s) {}
~NCDeleter()223 TEST_CONSTEXPR_CXX23 ~NCDeleter() {
224 assert(state_ >= 0);
225 state_ = -1;
226 }
227
state()228 TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)229 TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
230
operator()231 TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete p; }
232 };
233
234 template <class T>
235 class NCDeleter<T[]> {
236 int state_;
237 NCDeleter(NCDeleter const&);
238 NCDeleter& operator=(NCDeleter const&);
239
240 public:
NCDeleter()241 TEST_CONSTEXPR_CXX23 NCDeleter() : state_(0) {}
NCDeleter(int s)242 TEST_CONSTEXPR_CXX23 explicit NCDeleter(int s) : state_(s) {}
~NCDeleter()243 TEST_CONSTEXPR_CXX23 ~NCDeleter() {
244 assert(state_ >= 0);
245 state_ = -1;
246 }
247
state()248 TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)249 TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
250
operator()251 TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete[] p; }
252 };
253
254 // Non-copyable deleter
255 template <class T>
256 class NCConstDeleter {
257 int state_;
258 NCConstDeleter(NCConstDeleter const&);
259 NCConstDeleter& operator=(NCConstDeleter const&);
260
261 public:
NCConstDeleter()262 TEST_CONSTEXPR_CXX23 NCConstDeleter() : state_(0) {}
NCConstDeleter(int s)263 TEST_CONSTEXPR_CXX23 explicit NCConstDeleter(int s) : state_(s) {}
~NCConstDeleter()264 TEST_CONSTEXPR_CXX23 ~NCConstDeleter() {
265 assert(state_ >= 0);
266 state_ = -1;
267 }
268
state()269 TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)270 TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
271
operator()272 TEST_CONSTEXPR_CXX23 void operator()(T* p) const { delete p; }
273 };
274
275 template <class T>
276 class NCConstDeleter<T[]> {
277 int state_;
278 NCConstDeleter(NCConstDeleter const&);
279 NCConstDeleter& operator=(NCConstDeleter const&);
280
281 public:
NCConstDeleter()282 TEST_CONSTEXPR_CXX23 NCConstDeleter() : state_(0) {}
NCConstDeleter(int s)283 TEST_CONSTEXPR_CXX23 explicit NCConstDeleter(int s) : state_(s) {}
~NCConstDeleter()284 TEST_CONSTEXPR_CXX23 ~NCConstDeleter() {
285 assert(state_ >= 0);
286 state_ = -1;
287 }
288
state()289 TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)290 TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
291
operator()292 TEST_CONSTEXPR_CXX23 void operator()(T* p) const { delete[] p; }
293 };
294
295 // Non-copyable deleter
296 template <class T>
297 class CopyDeleter {
298 int state_;
299
300 public:
CopyDeleter()301 TEST_CONSTEXPR_CXX23 CopyDeleter() : state_(0) {}
CopyDeleter(int s)302 TEST_CONSTEXPR_CXX23 explicit CopyDeleter(int s) : state_(s) {}
~CopyDeleter()303 TEST_CONSTEXPR_CXX23 ~CopyDeleter() {
304 assert(state_ >= 0);
305 state_ = -1;
306 }
307
CopyDeleter(CopyDeleter const & other)308 TEST_CONSTEXPR_CXX23 CopyDeleter(CopyDeleter const& other) : state_(other.state_) {}
309 TEST_CONSTEXPR_CXX23 CopyDeleter& operator=(CopyDeleter const& other) {
310 state_ = other.state_;
311 return *this;
312 }
313
state()314 TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)315 TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
316
operator()317 TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete p; }
318 };
319
320 template <class T>
321 class CopyDeleter<T[]> {
322 int state_;
323
324 public:
CopyDeleter()325 TEST_CONSTEXPR_CXX23 CopyDeleter() : state_(0) {}
CopyDeleter(int s)326 TEST_CONSTEXPR_CXX23 explicit CopyDeleter(int s) : state_(s) {}
~CopyDeleter()327 TEST_CONSTEXPR_CXX23 ~CopyDeleter() {
328 assert(state_ >= 0);
329 state_ = -1;
330 }
331
CopyDeleter(CopyDeleter const & other)332 TEST_CONSTEXPR_CXX23 CopyDeleter(CopyDeleter const& other) : state_(other.state_) {}
333 TEST_CONSTEXPR_CXX23 CopyDeleter& operator=(CopyDeleter const& other) {
334 state_ = other.state_;
335 return *this;
336 }
337
state()338 TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)339 TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
340
operator()341 TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete[] p; }
342 };
343
344 struct test_deleter_base {
345 static int count;
346 static int dealloc_count;
347 };
348
349 int test_deleter_base::count = 0;
350 int test_deleter_base::dealloc_count = 0;
351
352 template <class T>
353 class test_deleter : public test_deleter_base {
354 int state_;
355
356 public:
test_deleter()357 test_deleter() : state_(0) { ++count; }
test_deleter(int s)358 explicit test_deleter(int s) : state_(s) { ++count; }
test_deleter(const test_deleter & d)359 test_deleter(const test_deleter& d) : state_(d.state_) { ++count; }
~test_deleter()360 ~test_deleter() {
361 assert(state_ >= 0);
362 --count;
363 state_ = -1;
364 }
365
state()366 int state() const { return state_; }
set_state(int i)367 void set_state(int i) { state_ = i; }
368
operator()369 void operator()(T* p) {
370 assert(state_ >= 0);
371 ++dealloc_count;
372 delete p;
373 }
374 #if TEST_STD_VER >= 11
375 test_deleter* operator&() const = delete;
376 #else
377
378 private:
379 test_deleter* operator&() const;
380 #endif
381 };
382
383 template <class T>
swap(test_deleter<T> & x,test_deleter<T> & y)384 void swap(test_deleter<T>& x, test_deleter<T>& y) {
385 test_deleter<T> t(std::move(x));
386 x = std::move(y);
387 y = std::move(t);
388 }
389
390 #if TEST_STD_VER >= 11
391
392 template <class T, std::size_t ID = 0>
393 class PointerDeleter {
394 PointerDeleter(const PointerDeleter&);
395 PointerDeleter& operator=(const PointerDeleter&);
396
397 public:
398 typedef min_pointer<T, std::integral_constant<std::size_t, ID>> pointer;
399
400 TEST_CONSTEXPR_CXX23 PointerDeleter() = default;
401 TEST_CONSTEXPR_CXX23 PointerDeleter(PointerDeleter&&) = default;
402 TEST_CONSTEXPR_CXX23 PointerDeleter& operator=(PointerDeleter&&) = default;
PointerDeleter(int)403 TEST_CONSTEXPR_CXX23 explicit PointerDeleter(int) {}
404
405 template <class U>
406 TEST_CONSTEXPR_CXX23
407 PointerDeleter(PointerDeleter<U, ID>&&, typename std::enable_if<!std::is_same<U, T>::value>::type* = 0) {}
408
operator()409 TEST_CONSTEXPR_CXX23 void operator()(pointer p) {
410 if (p) {
411 delete std::addressof(*p);
412 }
413 }
414
415 private:
416 template <class U>
417 PointerDeleter(const PointerDeleter<U, ID>&, typename std::enable_if<!std::is_same<U, T>::value>::type* = 0);
418 };
419
420 template <class T, std::size_t ID>
421 class PointerDeleter<T[], ID> {
422 PointerDeleter(const PointerDeleter&);
423 PointerDeleter& operator=(const PointerDeleter&);
424
425 public:
426 typedef min_pointer<T, std::integral_constant<std::size_t, ID> > pointer;
427
428 TEST_CONSTEXPR_CXX23 PointerDeleter() = default;
429 TEST_CONSTEXPR_CXX23 PointerDeleter(PointerDeleter&&) = default;
430 TEST_CONSTEXPR_CXX23 PointerDeleter& operator=(PointerDeleter&&) = default;
PointerDeleter(int)431 TEST_CONSTEXPR_CXX23 explicit PointerDeleter(int) {}
432
433 template <class U>
434 TEST_CONSTEXPR_CXX23
435 PointerDeleter(PointerDeleter<U, ID>&&, typename std::enable_if<!std::is_same<U, T>::value>::type* = 0) {}
436
operator()437 TEST_CONSTEXPR_CXX23 void operator()(pointer p) {
438 if (p) {
439 delete[] std::addressof(*p);
440 }
441 }
442
443 private:
444 template <class U>
445 PointerDeleter(const PointerDeleter<U, ID>&, typename std::enable_if<!std::is_same<U, T>::value>::type* = 0);
446 };
447
448 #endif // TEST_STD_VER >= 11
449
450 template <class T>
451 class DefaultCtorDeleter {
452 int state_;
453
454 public:
state()455 TEST_CONSTEXPR_CXX23 int state() const { return state_; }
operator()456 TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete p; }
457 };
458
459 template <class T>
460 class DefaultCtorDeleter<T[]> {
461 int state_;
462
463 public:
state()464 TEST_CONSTEXPR_CXX23 int state() const { return state_; }
operator()465 TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete[] p; }
466 };
467
468 #endif // SUPPORT_DELETER_TYPES_H
469