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