Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(98)

Side by Side Diff: include/private/SkUniquePtr.h

Issue 1436033003: skstd -> std for unique_ptr (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: more functions Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « include/private/SkTemplates.h ('k') | src/core/SkSharedMutex.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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
OLDNEW
« no previous file with comments | « include/private/SkTemplates.h ('k') | src/core/SkSharedMutex.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698