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