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) {}
196 template <class U>
CDeleter(const CDeleter<U> & d)197 CDeleter(const CDeleter<U>& d)
198 : state_(d.state()) {}
199
~CDeleter()200 ~CDeleter() {assert(state_ >= 0); state_ = -1;}
201
state()202 int state() const {return state_;}
set_state(int i)203 void set_state(int i) {state_ = i;}
204
operator()205 void operator()(T* p) {delete [] p;}
206 };
207
208 template <class T>
209 void
swap(CDeleter<T> & x,CDeleter<T> & y)210 swap(CDeleter<T>& x, CDeleter<T>& y)
211 {
212 CDeleter<T> t(std::move(x));
213 x = std::move(y);
214 y = std::move(t);
215 }
216
217 // Non-copyable deleter
218 template <class T>
219 class NCDeleter
220 {
221 int state_;
222 NCDeleter(NCDeleter const&);
223 NCDeleter& operator=(NCDeleter const&);
224 public:
225
NCDeleter()226 NCDeleter() : state_(0) {}
NCDeleter(int s)227 explicit NCDeleter(int s) : state_(s) {}
~NCDeleter()228 ~NCDeleter() {assert(state_ >= 0); state_ = -1;}
229
state()230 int state() const {return state_;}
set_state(int i)231 void set_state(int i) {state_ = i;}
232
operator()233 void operator()(T* p) {delete p;}
234 };
235
236
237 template <class T>
238 class NCDeleter<T[]>
239 {
240 int state_;
241 NCDeleter(NCDeleter const&);
242 NCDeleter& operator=(NCDeleter const&);
243 public:
244
NCDeleter()245 NCDeleter() : state_(0) {}
NCDeleter(int s)246 explicit NCDeleter(int s) : state_(s) {}
~NCDeleter()247 ~NCDeleter() {assert(state_ >= 0); state_ = -1;}
248
state()249 int state() const {return state_;}
set_state(int i)250 void set_state(int i) {state_ = i;}
251
operator()252 void operator()(T* p) {delete [] p;}
253 };
254
255
256 // Non-copyable deleter
257 template <class T>
258 class NCConstDeleter
259 {
260 int state_;
261 NCConstDeleter(NCConstDeleter const&);
262 NCConstDeleter& operator=(NCConstDeleter const&);
263 public:
264
NCConstDeleter()265 NCConstDeleter() : state_(0) {}
NCConstDeleter(int s)266 explicit NCConstDeleter(int s) : state_(s) {}
~NCConstDeleter()267 ~NCConstDeleter() {assert(state_ >= 0); state_ = -1;}
268
state()269 int state() const {return state_;}
set_state(int i)270 void set_state(int i) {state_ = i;}
271
operator()272 void operator()(T* p) const {delete p;}
273 };
274
275
276 template <class T>
277 class NCConstDeleter<T[]>
278 {
279 int state_;
280 NCConstDeleter(NCConstDeleter const&);
281 NCConstDeleter& operator=(NCConstDeleter const&);
282 public:
283
NCConstDeleter()284 NCConstDeleter() : state_(0) {}
NCConstDeleter(int s)285 explicit NCConstDeleter(int s) : state_(s) {}
~NCConstDeleter()286 ~NCConstDeleter() {assert(state_ >= 0); state_ = -1;}
287
state()288 int state() const {return state_;}
set_state(int i)289 void set_state(int i) {state_ = i;}
290
operator()291 void operator()(T* p) const {delete [] p;}
292 };
293
294
295 // Non-copyable deleter
296 template <class T>
297 class CopyDeleter
298 {
299 int state_;
300 public:
301
CopyDeleter()302 CopyDeleter() : state_(0) {}
CopyDeleter(int s)303 explicit CopyDeleter(int s) : state_(s) {}
~CopyDeleter()304 ~CopyDeleter() {assert(state_ >= 0); state_ = -1;}
305
CopyDeleter(CopyDeleter const & other)306 CopyDeleter(CopyDeleter const& other) : state_(other.state_) {}
307 CopyDeleter& operator=(CopyDeleter const& other) {
308 state_ = other.state_;
309 return *this;
310 }
311
state()312 int state() const {return state_;}
set_state(int i)313 void set_state(int i) {state_ = i;}
314
operator()315 void operator()(T* p) {delete p;}
316 };
317
318
319 template <class T>
320 class CopyDeleter<T[]>
321 {
322 int state_;
323
324 public:
325
CopyDeleter()326 CopyDeleter() : state_(0) {}
CopyDeleter(int s)327 explicit CopyDeleter(int s) : state_(s) {}
~CopyDeleter()328 ~CopyDeleter() {assert(state_ >= 0); state_ = -1;}
329
CopyDeleter(CopyDeleter const & other)330 CopyDeleter(CopyDeleter const& other) : state_(other.state_) {}
331 CopyDeleter& operator=(CopyDeleter const& other) {
332 state_ = other.state_;
333 return *this;
334 }
335
state()336 int state() const {return state_;}
set_state(int i)337 void set_state(int i) {state_ = i;}
338
operator()339 void operator()(T* p) {delete [] p;}
340 };
341
342
343 struct test_deleter_base
344 {
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
354 : public test_deleter_base
355 {
356 int state_;
357
358 public:
359
test_deleter()360 test_deleter() : state_(0) {++count;}
test_deleter(int s)361 explicit test_deleter(int s) : state_(s) {++count;}
test_deleter(const test_deleter & d)362 test_deleter(const test_deleter& d)
363 : state_(d.state_) {++count;}
~test_deleter()364 ~test_deleter() {assert(state_ >= 0); --count; state_ = -1;}
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) {assert(state_ >= 0); ++dealloc_count; delete p;}
370 #if TEST_STD_VER >= 11
371 test_deleter* operator&() const = delete;
372 #else
373 private:
374 test_deleter* operator&() const;
375 #endif
376 };
377
378 template <class T>
379 void
swap(test_deleter<T> & x,test_deleter<T> & y)380 swap(test_deleter<T>& x, test_deleter<T>& y)
381 {
382 test_deleter<T> t(std::move(x));
383 x = std::move(y);
384 y = std::move(t);
385 }
386
387 #if TEST_STD_VER >= 11
388
389 template <class T, size_t ID = 0>
390 class PointerDeleter
391 {
392 PointerDeleter(const PointerDeleter&);
393 PointerDeleter& operator=(const PointerDeleter&);
394
395 public:
396 typedef min_pointer<T, std::integral_constant<size_t, ID>> pointer;
397
398 PointerDeleter() = default;
399 PointerDeleter(PointerDeleter&&) = default;
400 PointerDeleter& operator=(PointerDeleter&&) = default;
PointerDeleter(int)401 explicit PointerDeleter(int) {}
402
403 template <class U>
404 PointerDeleter(PointerDeleter<U, ID>&&,
405 typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
406 {}
407
operator()408 void operator()(pointer p) { if (p) { delete std::addressof(*p); }}
409
410 private:
411 template <class U>
412 PointerDeleter(const PointerDeleter<U, ID>&,
413 typename std::enable_if<!std::is_same<U, T>::value>::type* = 0);
414 };
415
416
417 template <class T, size_t ID>
418 class PointerDeleter<T[], ID>
419 {
420 PointerDeleter(const PointerDeleter&);
421 PointerDeleter& operator=(const PointerDeleter&);
422
423 public:
424 typedef min_pointer<T, std::integral_constant<size_t, ID> > pointer;
425
426 PointerDeleter() = default;
427 PointerDeleter(PointerDeleter&&) = default;
428 PointerDeleter& operator=(PointerDeleter&&) = default;
PointerDeleter(int)429 explicit PointerDeleter(int) {}
430
431 template <class U>
432 PointerDeleter(PointerDeleter<U, ID>&&,
433 typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
434 {}
435
operator()436 void operator()(pointer p) { if (p) { delete [] std::addressof(*p); }}
437
438 private:
439 template <class U>
440 PointerDeleter(const PointerDeleter<U, ID>&,
441 typename std::enable_if<!std::is_same<U, T>::value>::type* = 0);
442 };
443
444 #endif // TEST_STD_VER >= 11
445
446 #endif // SUPPORT_DELETER_TYPES_H
447