OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2015 Google Inc. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license that can be | |
5 * found in the LICENSE file. | |
6 */ | |
7 | |
8 #ifndef SkUniquePtr_DEFINED | |
9 #define SkUniquePtr_DEFINED | |
10 | |
11 #include "SkTLogic.h" | |
12 #include <cstddef> | |
13 #include <utility> | |
14 | |
15 namespace skstd { | |
16 | |
17 template <typename T> struct default_delete { | |
18 /*constexpr*/ default_delete() /*noexcept*/ = default; | |
19 | |
20 template <typename U, typename = enable_if_t<is_convertible<U*, T*>::value>> | |
21 default_delete(const default_delete<U>&) /*noexcept*/ {} | |
22 | |
23 void operator()(T* obj) const { | |
24 static_assert(sizeof(T) > 0, "Deleting pointer to incomplete type!"); | |
25 delete obj; | |
26 } | |
27 }; | |
28 template <typename T> struct default_delete<T[]> { | |
29 /*constexpr*/ default_delete() /*noexcept*/ = default; | |
30 | |
31 void operator()(T* obj) const { | |
32 static_assert(sizeof(T) > 0, "Deleting pointer to incomplete type!"); | |
33 delete [] obj; | |
34 } | |
35 }; | |
36 | |
37 template <typename T, typename D = default_delete<T>> class unique_ptr { | |
38 // remove_reference_t<D>::pointer if that type exists, otherwise T*. | |
39 struct pointer_type_detector { | |
40 template <typename U> static typename U::pointer detector(typename U::po
inter*); | |
41 template <typename U> static T* detector(...); | |
42 using type = decltype(detector<remove_reference_t<D>>(0)); | |
43 }; | |
44 | |
45 public: | |
46 using pointer = typename pointer_type_detector::type; | |
47 using element_type = T; | |
48 using deleter_type = D; | |
49 | |
50 private: | |
51 template <typename B, bool = std::is_empty<B>::value /*&& !is_final<B>::valu
e*/> | |
52 struct compressed_base : private B { | |
53 /*constexpr*/ compressed_base() : B() {} | |
54 /*constexpr*/ compressed_base(const B& b) : B(b) {} | |
55 /*constexpr*/ compressed_base(B&& b) : B(std::move(b)) {} | |
56 /*constexpr*/ B& get() /*noexcept*/ { return *this; } | |
57 /*constexpr*/ B const& get() const /*noexcept*/ { return *this; } | |
58 void swap(compressed_base&) /*noexcept*/ { } | |
59 }; | |
60 | |
61 template <typename B> struct compressed_base<B, false> { | |
62 B fb; | |
63 /*constexpr*/ compressed_base() : B() {} | |
64 /*constexpr*/ compressed_base(const B& b) : fb(b) {} | |
65 /*constexpr*/ compressed_base(B&& b) : fb(std::move(b)) {} | |
66 /*constexpr*/ B& get() /*noexcept*/ { return fb; } | |
67 /*constexpr*/ B const& get() const /*noexcept*/ { return fb; } | |
68 void swap(compressed_base& that) /*noexcept*/ { SkTSwap(fb, that.fB); } | |
69 }; | |
70 | |
71 struct compressed_data : private compressed_base<deleter_type> { | |
72 pointer fPtr; | |
73 /*constexpr*/ compressed_data() : compressed_base<deleter_type>(), fPtr(
) {} | |
74 /*constexpr*/ compressed_data(const pointer& ptr, const deleter_type& d) | |
75 : compressed_base<deleter_type>(d), fPtr(ptr) {} | |
76 template <typename U1, typename U2, typename = enable_if_t< | |
77 is_convertible<U1, pointer>::value && is_convertible<U2, deleter_typ
e>::value | |
78 >> /*constexpr*/ compressed_data(U1&& ptr, U2&& d) | |
79 : compressed_base<deleter_type>(std::forward<U2>(d)), fPtr(std::forw
ard<U1>(ptr)) {} | |
80 /*constexpr*/ pointer& getPointer() /*noexcept*/ { return fPtr; } | |
81 /*constexpr*/ pointer const& getPointer() const /*noexcept*/ { return fP
tr; } | |
82 /*constexpr*/ deleter_type& getDeleter() /*noexcept*/ { | |
83 return compressed_base<deleter_type>::get(); | |
84 } | |
85 /*constexpr*/ deleter_type const& getDeleter() const /*noexcept*/ { | |
86 return compressed_base<deleter_type>::get(); | |
87 } | |
88 void swap(compressed_data& that) /*noexcept*/ { | |
89 compressed_base<deleter_type>::swap(static_cast<compressed_base<dele
ter_type>>(that)); | |
90 SkTSwap(fPtr, that.fPtr); | |
91 } | |
92 }; | |
93 compressed_data data; | |
94 | |
95 public: | |
96 /*constexpr*/ unique_ptr() /*noexcept*/ : data() { | |
97 static_assert(!std::is_pointer<deleter_type>::value, "Deleter nullptr fu
nction pointer!"); | |
98 } | |
99 | |
100 /*constexpr*/ unique_ptr(std::nullptr_t) /*noexcept*/ : unique_ptr() { } | |
101 | |
102 explicit unique_ptr(pointer ptr) /*noexcept*/ : data(ptr, deleter_type()) { | |
103 static_assert(!std::is_pointer<deleter_type>::value, "Deleter nullptr fu
nction pointer!"); | |
104 } | |
105 | |
106 unique_ptr(pointer ptr, | |
107 conditional_t<std::is_reference<deleter_type>::value, | |
108 deleter_type, const deleter_type&> d) | |
109 /*noexcept*/ : data(ptr, d) | |
110 {} | |
111 | |
112 unique_ptr(pointer ptr, remove_reference_t<deleter_type>&& d) /*noexcept*/ | |
113 : data(std::move(ptr), std::move(d)) | |
114 { | |
115 static_assert(!std::is_reference<deleter_type>::value, | |
116 "Binding an rvalue reference deleter as an lvalue reference deleter
is not allowed."); | |
117 } | |
118 | |
119 | |
120 unique_ptr(unique_ptr&& that) /*noexcept*/ | |
121 : data(that.release(), std::forward<deleter_type>(that.get_deleter())) | |
122 {} | |
123 | |
124 template <typename U, typename ThatD, typename = enable_if_t< | |
125 is_convertible<typename unique_ptr<U, ThatD>::pointer, pointer>::value &
& | |
126 !std::is_array<U>::value && | |
127 conditional_t<std::is_reference<D>::value, | |
128 std::is_same<ThatD, D>, | |
129 is_convertible<ThatD, D>>::value>> | |
130 unique_ptr(unique_ptr<U, ThatD>&& that) /*noexcept*/ | |
131 : data(that.release(), std::forward<ThatD>(that.get_deleter())) | |
132 {} | |
133 | |
134 ~unique_ptr() /*noexcept*/ { | |
135 pointer& ptr = data.getPointer(); | |
136 if (ptr != nullptr) { | |
137 get_deleter()(ptr); | |
138 } | |
139 ptr = pointer(); | |
140 } | |
141 | |
142 unique_ptr& operator=(unique_ptr&& that) /*noexcept*/ { | |
143 reset(that.release()); | |
144 get_deleter() = std::forward<deleter_type>(that.get_deleter()); | |
145 return *this; | |
146 } | |
147 | |
148 template <typename U, typename ThatD> enable_if_t< | |
149 is_convertible<typename unique_ptr<U, ThatD>::pointer, pointer>::value &
& | |
150 !std::is_array<U>::value, | |
151 unique_ptr&> operator=(unique_ptr<U, ThatD>&& that) /*noexcept*/ { | |
152 reset(that.release()); | |
153 get_deleter() = std::forward<ThatD>(that.get_deleter()); | |
154 return *this; | |
155 } | |
156 | |
157 unique_ptr& operator=(std::nullptr_t) /*noexcept*/ { | |
158 reset(); | |
159 return *this; | |
160 } | |
161 | |
162 add_lvalue_reference_t<element_type> operator*() const { | |
163 SkASSERT(get() != pointer()); | |
164 return *get(); | |
165 } | |
166 | |
167 pointer operator->() const /*noexcept*/ { | |
168 SkASSERT(get() != pointer()); | |
169 return get(); | |
170 } | |
171 | |
172 pointer get() const /*noexcept*/ { | |
173 return data.getPointer(); | |
174 } | |
175 | |
176 deleter_type& get_deleter() /*noexcept*/ { | |
177 return data.getDeleter(); | |
178 } | |
179 | |
180 const deleter_type& get_deleter() const /*noexcept*/ { | |
181 return data.getDeleter(); | |
182 } | |
183 | |
184 //explicit operator bool() const noexcept { | |
185 bool is_attached() const /*noexcept*/ { | |
186 return get() == pointer() ? false : true; | |
187 } | |
188 | |
189 pointer release() /*noexcept*/ { | |
190 pointer ptr = get(); | |
191 data.getPointer() = pointer(); | |
192 return ptr; | |
193 } | |
194 | |
195 void reset(pointer ptr = pointer()) /*noexcept*/ { | |
196 SkTSwap(data.getPointer(), ptr); | |
197 if (ptr != pointer()) { | |
198 get_deleter()(ptr); | |
199 } | |
200 } | |
201 | |
202 void swap(unique_ptr& that) /*noexcept*/ { | |
203 SkTSwap(data, that.data); | |
204 } | |
205 | |
206 unique_ptr(const unique_ptr&) = delete; | |
207 unique_ptr& operator=(const unique_ptr&) = delete; | |
208 }; | |
209 | |
210 template <typename T, typename D> class unique_ptr<T[], D> { | |
211 // remove_reference_t<D>::pointer if that type exists, otherwise T*. | |
212 struct pointer_type_detector { | |
213 template <typename U> static typename U::pointer detector(typename U::po
inter*); | |
214 template <typename U> static T* detector(...); | |
215 using type = decltype(detector<remove_reference_t<D>>(0)); | |
216 }; | |
217 | |
218 public: | |
219 using pointer = typename pointer_type_detector::type; | |
220 using element_type = T; | |
221 using deleter_type = D; | |
222 | |
223 private: | |
224 template <typename B, bool = std::is_empty<B>::value /*&& !is_final<B>::valu
e*/> | |
225 struct compressed_base : private B { | |
226 /*constexpr*/ compressed_base() : B() {} | |
227 /*constexpr*/ compressed_base(const B& b) : B(b) {} | |
228 /*constexpr*/ compressed_base(B&& b) : B(std::move(b)) {} | |
229 /*constexpr*/ B& get() /*noexcept*/ { return *this; } | |
230 /*constexpr*/ B const& get() const /*noexcept*/ { return *this; } | |
231 void swap(compressed_base&) /*noexcept*/ { } | |
232 }; | |
233 | |
234 template <typename B> struct compressed_base<B, false> { | |
235 B fb; | |
236 /*constexpr*/ compressed_base() : B() {} | |
237 /*constexpr*/ compressed_base(const B& b) : fb(b) {} | |
238 /*constexpr*/ compressed_base(B&& b) : fb(std::move(b)) {} | |
239 /*constexpr*/ B& get() /*noexcept*/ { return fb; } | |
240 /*constexpr*/ B const& get() const /*noexcept*/ { return fb; } | |
241 void swap(compressed_base& that) /*noexcept*/ { SkTSwap(fb, that.fB); } | |
242 }; | |
243 | |
244 struct compressed_data : private compressed_base<deleter_type> { | |
245 pointer fPtr; | |
246 /*constexpr*/ compressed_data() : compressed_base<deleter_type>(), fPtr(
) {} | |
247 /*constexpr*/ compressed_data(const pointer& ptr, const deleter_type& d) | |
248 : compressed_base<deleter_type>(d), fPtr(ptr) {} | |
249 template <typename U1, typename U2, typename = enable_if_t< | |
250 is_convertible<U1, pointer>::value && is_convertible<U2, deleter_typ
e>::value | |
251 >> /*constexpr*/ compressed_data(U1&& ptr, U2&& d) | |
252 : compressed_base<deleter_type>(std::forward<U2>(d)), fPtr(std::forw
ard<U1>(ptr)) {} | |
253 /*constexpr*/ pointer& getPointer() /*noexcept*/ { return fPtr; } | |
254 /*constexpr*/ pointer const& getPointer() const /*noexcept*/ { return fP
tr; } | |
255 /*constexpr*/ deleter_type& getDeleter() /*noexcept*/ { | |
256 return compressed_base<deleter_type>::get(); | |
257 } | |
258 /*constexpr*/ deleter_type const& getDeleter() const /*noexcept*/ { | |
259 return compressed_base<deleter_type>::get(); | |
260 } | |
261 void swap(compressed_data& that) /*noexcept*/ { | |
262 compressed_base<deleter_type>::swap(static_cast<compressed_base<dele
ter_type>>(that)); | |
263 SkTSwap(fPtr, that.fPtr); | |
264 } | |
265 }; | |
266 compressed_data data; | |
267 | |
268 public: | |
269 /*constexpr*/ unique_ptr() /*noexcept*/ : data() { | |
270 static_assert(!std::is_pointer<deleter_type>::value, "Deleter nullptr fu
nction pointer!"); | |
271 } | |
272 | |
273 /*constexpr*/ unique_ptr(std::nullptr_t) /*noexcept*/ : unique_ptr() { } | |
274 | |
275 explicit unique_ptr(pointer ptr) /*noexcept*/ : data(ptr, deleter_type()) { | |
276 static_assert(!std::is_pointer<deleter_type>::value, "Deleter nullptr fu
nction pointer!"); | |
277 } | |
278 | |
279 unique_ptr(pointer ptr, | |
280 conditional_t<std::is_reference<deleter_type>::value, | |
281 deleter_type, const deleter_type&> d) | |
282 /*noexcept*/ : data(ptr, d) | |
283 {} | |
284 | |
285 unique_ptr(pointer ptr, remove_reference_t<deleter_type>&& d) /*noexcept*/ | |
286 : data(std::move(ptr), std::move(d)) | |
287 { | |
288 static_assert(!std::is_reference<deleter_type>::value, | |
289 "Binding an rvalue reference deleter as an lvalue reference deleter
is not allowed."); | |
290 } | |
291 | |
292 unique_ptr(unique_ptr&& that) /*noexcept*/ | |
293 : data(that.release(), std::forward<deleter_type>(that.get_deleter())) | |
294 {} | |
295 | |
296 ~unique_ptr() { | |
297 pointer& ptr = data.getPointer(); | |
298 if (ptr != nullptr) { | |
299 get_deleter()(ptr); | |
300 } | |
301 ptr = pointer(); | |
302 } | |
303 | |
304 unique_ptr& operator=(unique_ptr&& that) /*noexcept*/ { | |
305 reset(that.release()); | |
306 get_deleter() = std::forward<deleter_type>(that.get_deleter()); | |
307 return *this; | |
308 } | |
309 | |
310 unique_ptr& operator=(std::nullptr_t) /*noexcept*/ { | |
311 reset(); | |
312 return *this; | |
313 } | |
314 | |
315 add_lvalue_reference_t<element_type> operator[](size_t i) const { | |
316 SkASSERT(get() != pointer()); | |
317 return get()[i]; | |
318 } | |
319 | |
320 pointer get() const /*noexcept*/ { | |
321 return data.getPointer(); | |
322 } | |
323 | |
324 deleter_type& get_deleter() /*noexcept*/ { | |
325 return data.getDeleter(); | |
326 } | |
327 | |
328 const deleter_type& get_deleter() const /*noexcept*/ { | |
329 return data.getDeleter(); | |
330 } | |
331 | |
332 //explicit operator bool() const noexcept { | |
333 bool is_attached() const /*noexcept*/ { | |
334 return get() == pointer() ? false : true; | |
335 } | |
336 | |
337 pointer release() /*noexcept*/ { | |
338 pointer ptr = get(); | |
339 data.getPointer() = pointer(); | |
340 return ptr; | |
341 } | |
342 | |
343 void reset(pointer ptr = pointer()) /*noexcept*/ { | |
344 SkTSwap(data.getPointer(), ptr); | |
345 if (ptr != pointer()) { | |
346 get_deleter()(ptr); | |
347 } | |
348 } | |
349 | |
350 template <typename U> void reset(U*) = delete; | |
351 | |
352 void swap(unique_ptr& that) /*noexcept*/ { | |
353 data.swap(that.data); | |
354 } | |
355 | |
356 unique_ptr(const unique_ptr&) = delete; | |
357 unique_ptr& operator=(const unique_ptr&) = delete; | |
358 }; | |
359 | |
360 template <typename T, typename D> | |
361 inline void swap(unique_ptr<T, D>& a, unique_ptr<T, D>& b) /*noexcept*/ { | |
362 a.swap(b); | |
363 } | |
364 | |
365 template <typename T, typename D, typename U, typename ThatD> | |
366 inline bool operator==(const unique_ptr<T, D>& a, const unique_ptr<U, ThatD>& b)
{ | |
367 return a.get() == b.get(); | |
368 } | |
369 | |
370 template <typename T, typename D> | |
371 inline bool operator==(const unique_ptr<T, D>& a, std::nullptr_t) /*noexcept*/ { | |
372 //return !a; | |
373 return !a.is_attached(); | |
374 } | |
375 | |
376 template <typename T, typename D> | |
377 inline bool operator==(std::nullptr_t, const unique_ptr<T, D>& b) /*noexcept*/ { | |
378 //return !b; | |
379 return !b.is_attached(); | |
380 } | |
381 | |
382 template <typename T, typename D, typename U, typename ThatD> | |
383 inline bool operator!=(const unique_ptr<T, D>& a, const unique_ptr<U, ThatD>& b)
{ | |
384 return a.get() != b.get(); | |
385 } | |
386 | |
387 template <typename T, typename D> | |
388 inline bool operator!=(const unique_ptr<T, D>& a, std::nullptr_t) /*noexcept*/ { | |
389 //return (bool)a; | |
390 return a.is_attached(); | |
391 } | |
392 | |
393 template <typename T, typename D> | |
394 inline bool operator!=(std::nullptr_t, const unique_ptr<T, D>& b) /*noexcept*/ { | |
395 //return (bool)b; | |
396 return b.is_attached(); | |
397 } | |
398 | |
399 } // namespace skstd | |
400 | |
401 #endif | |
OLD | NEW |