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
28template <class T>
29class Deleter
30{
31    int state_;
32
33    Deleter(const Deleter&);
34    Deleter& operator=(const Deleter&);
35
36public:
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
46    Deleter() : state_(0) {}
47    explicit Deleter(int s) : state_(s) {}
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
55private:
56    template <class U>
57        Deleter(const Deleter<U>& d,
58            typename std::enable_if<!std::is_same<U, T>::value>::type* = 0);
59public:
60    int state() const {return state_;}
61    void set_state(int i) {state_ = i;}
62
63    void operator()(T* p) {delete p;}
64};
65
66template <class T>
67class Deleter<T[]>
68{
69    int state_;
70
71    Deleter(const Deleter&);
72    Deleter& operator=(const Deleter&);
73
74public:
75
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
84    Deleter() : state_(0) {}
85    explicit Deleter(int s) : state_(s) {}
86    ~Deleter() {assert(state_ >= 0); state_ = -1;}
87
88    int state() const {return state_;}
89    void set_state(int i) {state_ = i;}
90
91    void operator()(T* p) {delete [] p;}
92};
93
94#else // TEST_STD_VER < 11
95
96template <class T>
97class Deleter
98{
99    mutable int state_;
100
101public:
102    Deleter() : state_(0) {}
103    explicit Deleter(int s) : state_(s) {}
104
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
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
121public:
122    int state() const {return state_;}
123    void set_state(int i) {state_ = i;}
124
125    void operator()(T* p) {delete p;}
126};
127
128template <class T>
129class Deleter<T[]>
130{
131    mutable int state_;
132
133public:
134
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
144    Deleter() : state_(0) {}
145    explicit Deleter(int s) : state_(s) {}
146    ~Deleter() {assert(state_ >= 0); state_ = -1;}
147
148    int state() const {return state_;}
149    void set_state(int i) {state_ = i;}
150
151    void operator()(T* p) {delete [] p;}
152};
153
154#endif
155
156template <class T>
157void
158swap(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
166template <class T>
167class CDeleter
168{
169    int state_;
170
171public:
172
173    CDeleter() : state_(0) {}
174    explicit CDeleter(int s) : state_(s) {}
175    ~CDeleter() {assert(state_ >= 0); state_ = -1;}
176
177    template <class U>
178        CDeleter(const CDeleter<U>& d)
179            : state_(d.state()) {}
180
181    int state() const {return state_;}
182    void set_state(int i) {state_ = i;}
183
184    void operator()(T* p) {delete p;}
185};
186
187template <class T>
188class CDeleter<T[]>
189{
190    int state_;
191
192public:
193
194    CDeleter() : state_(0) {}
195    explicit CDeleter(int s) : state_(s) {}
196    ~CDeleter() {assert(state_ >= 0); state_ = -1;}
197
198    int state() const {return state_;}
199    void set_state(int i) {state_ = i;}
200
201    void operator()(T* p) {delete [] p;}
202};
203
204template <class T>
205void
206swap(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
214template <class T>
215class NCDeleter
216{
217    int state_;
218    NCDeleter(NCDeleter const&);
219    NCDeleter& operator=(NCDeleter const&);
220public:
221
222    NCDeleter() : state_(0) {}
223    explicit NCDeleter(int s) : state_(s) {}
224    ~NCDeleter() {assert(state_ >= 0); state_ = -1;}
225
226    int state() const {return state_;}
227    void set_state(int i) {state_ = i;}
228
229    void operator()(T* p) {delete p;}
230};
231
232
233template <class T>
234class NCDeleter<T[]>
235{
236    int state_;
237    NCDeleter(NCDeleter const&);
238    NCDeleter& operator=(NCDeleter const&);
239public:
240
241    NCDeleter() : state_(0) {}
242    explicit NCDeleter(int s) : state_(s) {}
243    ~NCDeleter() {assert(state_ >= 0); state_ = -1;}
244
245    int state() const {return state_;}
246    void set_state(int i) {state_ = i;}
247
248    void operator()(T* p) {delete [] p;}
249};
250
251
252// Non-copyable deleter
253template <class T>
254class NCConstDeleter
255{
256    int state_;
257    NCConstDeleter(NCConstDeleter const&);
258    NCConstDeleter& operator=(NCConstDeleter const&);
259public:
260
261    NCConstDeleter() : state_(0) {}
262    explicit NCConstDeleter(int s) : state_(s) {}
263    ~NCConstDeleter() {assert(state_ >= 0); state_ = -1;}
264
265    int state() const {return state_;}
266    void set_state(int i) {state_ = i;}
267
268    void operator()(T* p) const {delete p;}
269};
270
271
272template <class T>
273class NCConstDeleter<T[]>
274{
275    int state_;
276    NCConstDeleter(NCConstDeleter const&);
277    NCConstDeleter& operator=(NCConstDeleter const&);
278public:
279
280    NCConstDeleter() : state_(0) {}
281    explicit NCConstDeleter(int s) : state_(s) {}
282    ~NCConstDeleter() {assert(state_ >= 0); state_ = -1;}
283
284    int state() const {return state_;}
285    void set_state(int i) {state_ = i;}
286
287    void operator()(T* p) const {delete [] p;}
288};
289
290
291// Non-copyable deleter
292template <class T>
293class CopyDeleter
294{
295    int state_;
296public:
297
298    CopyDeleter() : state_(0) {}
299    explicit CopyDeleter(int s) : state_(s) {}
300    ~CopyDeleter() {assert(state_ >= 0); state_ = -1;}
301
302    CopyDeleter(CopyDeleter const& other) : state_(other.state_) {}
303    CopyDeleter& operator=(CopyDeleter const& other) {
304        state_ = other.state_;
305        return *this;
306    }
307
308    int state() const {return state_;}
309    void set_state(int i) {state_ = i;}
310
311    void operator()(T* p) {delete p;}
312};
313
314
315template <class T>
316class CopyDeleter<T[]>
317{
318    int state_;
319
320public:
321
322    CopyDeleter() : state_(0) {}
323    explicit CopyDeleter(int s) : state_(s) {}
324    ~CopyDeleter() {assert(state_ >= 0); state_ = -1;}
325
326    CopyDeleter(CopyDeleter const& other) : state_(other.state_) {}
327    CopyDeleter& operator=(CopyDeleter const& other) {
328        state_ = other.state_;
329        return *this;
330    }
331
332    int state() const {return state_;}
333    void set_state(int i) {state_ = i;}
334
335    void operator()(T* p) {delete [] p;}
336};
337
338
339struct test_deleter_base
340{
341    static int count;
342    static int dealloc_count;
343};
344
345int test_deleter_base::count = 0;
346int test_deleter_base::dealloc_count = 0;
347
348template <class T>
349class test_deleter
350    : public test_deleter_base
351{
352    int state_;
353
354public:
355
356    test_deleter() : state_(0) {++count;}
357    explicit test_deleter(int s) : state_(s) {++count;}
358    test_deleter(const test_deleter& d)
359        : state_(d.state_) {++count;}
360    ~test_deleter() {assert(state_ >= 0); --count; state_ = -1;}
361
362    int state() const {return state_;}
363    void set_state(int i) {state_ = i;}
364
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
369private:
370  test_deleter* operator&() const;
371#endif
372};
373
374template <class T>
375void
376swap(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
385template <class T, size_t ID = 0>
386class PointerDeleter
387{
388    PointerDeleter(const PointerDeleter&);
389    PointerDeleter& operator=(const PointerDeleter&);
390
391public:
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;
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
404    void operator()(pointer p) { if (p) { delete std::addressof(*p); }}
405
406private:
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
413template <class T, size_t ID>
414class PointerDeleter<T[], ID>
415{
416    PointerDeleter(const PointerDeleter&);
417    PointerDeleter& operator=(const PointerDeleter&);
418
419public:
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;
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
432    void operator()(pointer p) { if (p) { delete [] std::addressof(*p); }}
433
434private:
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