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 DELETER_H
17#define DELETER_H
18
19#include <type_traits>
20#include <cassert>
21
22template <class T>
23class Deleter
24{
25    int state_;
26
27#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
28    Deleter(const Deleter&);
29    Deleter& operator=(const Deleter&);
30#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
31    Deleter(Deleter&);
32    Deleter& operator=(Deleter&);
33#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
34
35public:
36#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
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#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
45    operator std::__rv<Deleter>() {return std::__rv<Deleter>(*this);}
46    Deleter(std::__rv<Deleter> r) : state_(r->state_) {r->state_ = 0;}
47    Deleter& operator=(std::__rv<Deleter> r)
48    {
49        state_ = r->state_;
50        r->state_ = 0;
51        return *this;
52    }
53#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
54
55    Deleter() : state_(0) {}
56    explicit Deleter(int s) : state_(s) {}
57    ~Deleter() {assert(state_ >= 0); state_ = -1;}
58
59#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
60    template <class U>
61        Deleter(Deleter<U>&& d,
62            typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
63            : state_(d.state()) {d.set_state(0);}
64
65private:
66    template <class U>
67        Deleter(const Deleter<U>& d,
68            typename std::enable_if<!std::is_same<U, T>::value>::type* = 0);
69#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
70    template <class U>
71        Deleter(Deleter<U> d,
72            typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
73            : state_(d.state()) {}
74#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
75public:
76    int state() const {return state_;}
77    void set_state(int i) {state_ = i;}
78
79    void operator()(T* p) {delete p;}
80};
81
82template <class T>
83class Deleter<T[]>
84{
85    int state_;
86
87#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
88    Deleter(const Deleter&);
89    Deleter& operator=(const Deleter&);
90#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
91    Deleter(Deleter&);
92    Deleter& operator=(Deleter&);
93#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
94
95public:
96#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
97    Deleter(Deleter&& r) : state_(r.state_) {r.state_ = 0;}
98    Deleter& operator=(Deleter&& r)
99    {
100        state_ = r.state_;
101        r.state_ = 0;
102        return *this;
103    }
104#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
105    operator std::__rv<Deleter>() {return std::__rv<Deleter>(*this);}
106    Deleter(std::__rv<Deleter> r) : state_(r->state_) {r->state_ = 0;}
107    Deleter& operator=(std::__rv<Deleter> r)
108    {
109        state_ = r->state_;
110        r->state_ = 0;
111        return *this;
112    }
113#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
114
115    Deleter() : state_(0) {}
116    explicit Deleter(int s) : state_(s) {}
117    ~Deleter() {assert(state_ >= 0); state_ = -1;}
118
119    int state() const {return state_;}
120    void set_state(int i) {state_ = i;}
121
122    void operator()(T* p) {delete [] p;}
123};
124
125template <class T>
126void
127swap(Deleter<T>& x, Deleter<T>& y)
128{
129    Deleter<T> t(std::move(x));
130    x = std::move(y);
131    y = std::move(t);
132}
133
134template <class T>
135class CDeleter
136{
137    int state_;
138
139public:
140
141    CDeleter() : state_(0) {}
142    explicit CDeleter(int s) : state_(s) {}
143    ~CDeleter() {assert(state_ >= 0); state_ = -1;}
144
145    template <class U>
146        CDeleter(const CDeleter<U>& d)
147            : state_(d.state()) {}
148
149    int state() const {return state_;}
150    void set_state(int i) {state_ = i;}
151
152    void operator()(T* p) {delete p;}
153};
154
155template <class T>
156class CDeleter<T[]>
157{
158    int state_;
159
160public:
161
162    CDeleter() : state_(0) {}
163    explicit CDeleter(int s) : state_(s) {}
164    ~CDeleter() {assert(state_ >= 0); state_ = -1;}
165
166    int state() const {return state_;}
167    void set_state(int i) {state_ = i;}
168
169    void operator()(T* p) {delete [] p;}
170};
171
172template <class T>
173void
174swap(CDeleter<T>& x, CDeleter<T>& y)
175{
176    CDeleter<T> t(std::move(x));
177    x = std::move(y);
178    y = std::move(t);
179}
180
181#endif  // DELETER_H
182