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