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