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