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