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 
22 template <class T>
23 class 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 
35 public:
36 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
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 #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 
Deleter()55     Deleter() : state_(0) {}
Deleter(int s)56     explicit Deleter(int s) : state_(s) {}
~Deleter()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 
65 private:
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
75 public:
state()76     int state() const {return state_;}
set_state(int i)77     void set_state(int i) {state_ = i;}
78 
operator()79     void operator()(T* p) {delete p;}
80 };
81 
82 template <class T>
83 class 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 
95 public:
96 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Deleter(Deleter && r)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 
Deleter()115     Deleter() : state_(0) {}
Deleter(int s)116     explicit Deleter(int s) : state_(s) {}
~Deleter()117     ~Deleter() {assert(state_ >= 0); state_ = -1;}
118 
state()119     int state() const {return state_;}
set_state(int i)120     void set_state(int i) {state_ = i;}
121 
operator()122     void operator()(T* p) {delete [] p;}
123 };
124 
125 template <class T>
126 void
swap(Deleter<T> & x,Deleter<T> & y)127 swap(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 
134 template <class T>
135 class CDeleter
136 {
137     int state_;
138 
139 public:
140 
CDeleter()141     CDeleter() : state_(0) {}
CDeleter(int s)142     explicit CDeleter(int s) : state_(s) {}
~CDeleter()143     ~CDeleter() {assert(state_ >= 0); state_ = -1;}
144 
145     template <class U>
CDeleter(const CDeleter<U> & d)146         CDeleter(const CDeleter<U>& d)
147             : state_(d.state()) {}
148 
state()149     int state() const {return state_;}
set_state(int i)150     void set_state(int i) {state_ = i;}
151 
operator()152     void operator()(T* p) {delete p;}
153 };
154 
155 template <class T>
156 class CDeleter<T[]>
157 {
158     int state_;
159 
160 public:
161 
CDeleter()162     CDeleter() : state_(0) {}
CDeleter(int s)163     explicit CDeleter(int s) : state_(s) {}
~CDeleter()164     ~CDeleter() {assert(state_ >= 0); state_ = -1;}
165 
state()166     int state() const {return state_;}
set_state(int i)167     void set_state(int i) {state_ = i;}
168 
operator()169     void operator()(T* p) {delete [] p;}
170 };
171 
172 template <class T>
173 void
swap(CDeleter<T> & x,CDeleter<T> & y)174 swap(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