OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Scopers help you manage ownership of a pointer, helping you easily manage a | 5 // Scopers help you manage ownership of a pointer, helping you easily manage a |
6 // pointer within a scope, and automatically destroying the pointer at the end | 6 // pointer within a scope, and automatically destroying the pointer at the end |
7 // of a scope. There are two main classes you will use, which correspond to the | 7 // of a scope. There are two main classes you will use, which correspond to the |
8 // operators new/delete and new[]/delete[]. | 8 // operators new/delete and new[]/delete[]. |
9 // | 9 // |
10 // Example usage (scoped_ptr<T>): | 10 // Example usage (scoped_ptr<T>): |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
79 | 79 |
80 // This is an implementation designed to match the anticipated future TR2 | 80 // This is an implementation designed to match the anticipated future TR2 |
81 // implementation of the scoped_ptr class. | 81 // implementation of the scoped_ptr class. |
82 | 82 |
83 #include <assert.h> | 83 #include <assert.h> |
84 #include <stddef.h> | 84 #include <stddef.h> |
85 #include <stdlib.h> | 85 #include <stdlib.h> |
86 | 86 |
87 #include <algorithm> // For std::swap(). | 87 #include <algorithm> // For std::swap(). |
88 #include <iosfwd> | 88 #include <iosfwd> |
89 #include <memory> | |
90 #include <utility> | |
89 | 91 |
90 #include "base/basictypes.h" | 92 #include "base/basictypes.h" |
91 #include "base/compiler_specific.h" | 93 #include "base/compiler_specific.h" |
92 #include "base/move.h" | 94 #include "base/move.h" |
93 #include "base/template_util.h" | 95 #include "base/template_util.h" |
94 | 96 |
95 namespace base { | 97 namespace base { |
96 | 98 |
97 namespace subtle { | 99 namespace subtle { |
98 class RefCountedBase; | 100 class RefCountedBase; |
99 class RefCountedThreadSafeBase; | 101 class RefCountedThreadSafeBase; |
100 } // namespace subtle | 102 } // namespace subtle |
101 | 103 |
102 // Function object which deletes its parameter, which must be a pointer. | |
103 // If C is an array type, invokes 'delete[]' on the parameter; otherwise, | |
104 // invokes 'delete'. The default deleter for scoped_ptr<T>. | |
105 template <class T> | |
106 struct DefaultDeleter { | |
dcheng
2015/11/11 16:18:34
I tried using a type alias, but apparently the sta
| |
107 DefaultDeleter() {} | |
108 template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) { | |
109 // IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor | |
110 // if U* is implicitly convertible to T* and U is not an array type. | |
111 // | |
112 // Correct implementation should use SFINAE to disable this | |
113 // constructor. However, since there are no other 1-argument constructors, | |
114 // using a COMPILE_ASSERT() based on is_convertible<> and requiring | |
115 // complete types is simpler and will cause compile failures for equivalent | |
116 // misuses. | |
117 // | |
118 // Note, the is_convertible<U*, T*> check also ensures that U is not an | |
119 // array. T is guaranteed to be a non-array, so any U* where U is an array | |
120 // cannot convert to T*. | |
121 enum { T_must_be_complete = sizeof(T) }; | |
122 enum { U_must_be_complete = sizeof(U) }; | |
123 COMPILE_ASSERT((base::is_convertible<U*, T*>::value), | |
124 U_ptr_must_implicitly_convert_to_T_ptr); | |
125 } | |
126 inline void operator()(T* ptr) const { | |
127 enum { type_must_be_complete = sizeof(T) }; | |
128 delete ptr; | |
129 } | |
130 }; | |
131 | |
132 // Specialization of DefaultDeleter for array types. | |
133 template <class T> | |
134 struct DefaultDeleter<T[]> { | |
135 inline void operator()(T* ptr) const { | |
136 enum { type_must_be_complete = sizeof(T) }; | |
137 delete[] ptr; | |
138 } | |
139 | |
140 private: | |
141 // Disable this operator for any U != T because it is undefined to execute | |
142 // an array delete when the static type of the array mismatches the dynamic | |
143 // type. | |
144 // | |
145 // References: | |
146 // C++98 [expr.delete]p3 | |
147 // http://cplusplus.github.com/LWG/lwg-defects.html#938 | |
148 template <typename U> void operator()(U* array) const; | |
149 }; | |
150 | |
151 template <class T, int n> | |
152 struct DefaultDeleter<T[n]> { | |
153 // Never allow someone to declare something like scoped_ptr<int[10]>. | |
154 COMPILE_ASSERT(sizeof(T) == -1, do_not_use_array_with_size_as_type); | |
155 }; | |
156 | |
157 // Function object which invokes 'free' on its parameter, which must be | 104 // Function object which invokes 'free' on its parameter, which must be |
158 // a pointer. Can be used to store malloc-allocated pointers in scoped_ptr: | 105 // a pointer. Can be used to store malloc-allocated pointers in scoped_ptr: |
159 // | 106 // |
160 // scoped_ptr<int, base::FreeDeleter> foo_ptr( | 107 // scoped_ptr<int, base::FreeDeleter> foo_ptr( |
161 // static_cast<int*>(malloc(sizeof(int)))); | 108 // static_cast<int*>(malloc(sizeof(int)))); |
162 struct FreeDeleter { | 109 struct FreeDeleter { |
163 inline void operator()(void* ptr) const { | 110 inline void operator()(void* ptr) const { |
164 free(ptr); | 111 free(ptr); |
165 } | 112 } |
166 }; | 113 }; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
201 template <typename U, typename V> | 148 template <typename U, typename V> |
202 scoped_ptr_impl(scoped_ptr_impl<U, V>* other) | 149 scoped_ptr_impl(scoped_ptr_impl<U, V>* other) |
203 : data_(other->release(), other->get_deleter()) { | 150 : data_(other->release(), other->get_deleter()) { |
204 // We do not support move-only deleters. We could modify our move | 151 // We do not support move-only deleters. We could modify our move |
205 // emulation to have base::subtle::move() and base::subtle::forward() | 152 // emulation to have base::subtle::move() and base::subtle::forward() |
206 // functions that are imperfect emulations of their C++11 equivalents, | 153 // functions that are imperfect emulations of their C++11 equivalents, |
207 // but until there's a requirement, just assume deleters are copyable. | 154 // but until there's a requirement, just assume deleters are copyable. |
208 } | 155 } |
209 | 156 |
210 template <typename U, typename V> | 157 template <typename U, typename V> |
158 void TakeState(std::unique_ptr<U, V>* other) { | |
159 reset(other->release()); | |
160 get_deleter() = other->get_deleter(); | |
161 } | |
162 | |
163 template <typename U, typename V> | |
211 void TakeState(scoped_ptr_impl<U, V>* other) { | 164 void TakeState(scoped_ptr_impl<U, V>* other) { |
212 // See comment in templated constructor above regarding lack of support | 165 // See comment in templated constructor above regarding lack of support |
213 // for move-only deleters. | 166 // for move-only deleters. |
214 reset(other->release()); | 167 reset(other->release()); |
215 get_deleter() = other->get_deleter(); | 168 get_deleter() = other->get_deleter(); |
216 } | 169 } |
217 | 170 |
218 ~scoped_ptr_impl() { | 171 ~scoped_ptr_impl() { |
219 // Match libc++, which calls reset() in its destructor. | 172 // Match libc++, which calls reset() in its destructor. |
220 // Use nullptr as the new value for three reasons: | 173 // Use nullptr as the new value for three reasons: |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
296 // | 249 // |
297 // The size of scoped_ptr is small. On most compilers, when using the | 250 // The size of scoped_ptr is small. On most compilers, when using the |
298 // DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will | 251 // DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will |
299 // increase the size proportional to whatever state they need to have. See | 252 // increase the size proportional to whatever state they need to have. See |
300 // comments inside scoped_ptr_impl<> for details. | 253 // comments inside scoped_ptr_impl<> for details. |
301 // | 254 // |
302 // Current implementation targets having a strict subset of C++11's | 255 // Current implementation targets having a strict subset of C++11's |
303 // unique_ptr<> features. Known deficiencies include not supporting move-only | 256 // unique_ptr<> features. Known deficiencies include not supporting move-only |
304 // deleteres, function pointers as deleters, and deleters with reference | 257 // deleteres, function pointers as deleters, and deleters with reference |
305 // types. | 258 // types. |
306 template <class T, class D = base::DefaultDeleter<T> > | 259 template <class T, class D = std::default_delete<T>> |
307 class scoped_ptr { | 260 class scoped_ptr { |
308 MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) | 261 MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) |
309 | 262 |
310 COMPILE_ASSERT(base::internal::IsNotRefCounted<T>::value, | 263 COMPILE_ASSERT(base::internal::IsNotRefCounted<T>::value, |
311 T_is_refcounted_type_and_needs_scoped_refptr); | 264 T_is_refcounted_type_and_needs_scoped_refptr); |
312 | 265 |
313 public: | 266 public: |
314 // The element and deleter types. | 267 // The element and deleter types. |
315 typedef T element_type; | 268 typedef T element_type; |
316 typedef D deleter_type; | 269 typedef D deleter_type; |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
415 } | 368 } |
416 | 369 |
417 // Release a pointer. | 370 // Release a pointer. |
418 // The return value is the current pointer held by this object. If this object | 371 // The return value is the current pointer held by this object. If this object |
419 // holds a nullptr, the return value is nullptr. After this operation, this | 372 // holds a nullptr, the return value is nullptr. After this operation, this |
420 // object will hold a nullptr, and will not own the object any more. | 373 // object will hold a nullptr, and will not own the object any more. |
421 element_type* release() WARN_UNUSED_RESULT { | 374 element_type* release() WARN_UNUSED_RESULT { |
422 return impl_.release(); | 375 return impl_.release(); |
423 } | 376 } |
424 | 377 |
378 // Conversion shims to help with the std::unique_ptr transition. | |
379 template <typename U, typename V> | |
380 scoped_ptr(std::unique_ptr<U, V>&& p) | |
381 : impl_(p.release(), p.get_deleter()) {} | |
382 | |
383 template <typename U, typename V> | |
384 scoped_ptr& operator=(std::unique_ptr<U, V>&& p) { | |
385 impl_.TakeState(&p); | |
386 return *this; | |
387 } | |
388 | |
389 template <typename U, typename V> | |
390 operator std::unique_ptr<U, V>() && { | |
danakj
2015/11/14 01:29:31
Vlad pointed out that this doesn't work yet in MSV
dcheng
2015/11/14 01:37:10
Argh. That's obnoxious. Having asymmetrical ways t
| |
391 return std::unique_ptr<U, V>(release(), get_deleter()); | |
392 } | |
393 | |
425 private: | 394 private: |
426 // Needed to reach into |impl_| in the constructor. | 395 // Needed to reach into |impl_| in the constructor. |
427 template <typename U, typename V> friend class scoped_ptr; | 396 template <typename U, typename V> friend class scoped_ptr; |
428 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_; | 397 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_; |
429 | 398 |
430 // Forbidden for API compatibility with std::unique_ptr. | 399 // Forbidden for API compatibility with std::unique_ptr. |
431 explicit scoped_ptr(int disallow_construction_from_null); | 400 explicit scoped_ptr(int disallow_construction_from_null); |
432 | 401 |
433 // Forbid comparison of scoped_ptr types. If U != T, it totally | 402 // Forbid comparison of scoped_ptr types. If U != T, it totally |
434 // doesn't make sense, and if U == T, it still doesn't make sense | 403 // doesn't make sense, and if U == T, it still doesn't make sense |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
520 } | 489 } |
521 | 490 |
522 // Release a pointer. | 491 // Release a pointer. |
523 // The return value is the current pointer held by this object. If this object | 492 // The return value is the current pointer held by this object. If this object |
524 // holds a nullptr, the return value is nullptr. After this operation, this | 493 // holds a nullptr, the return value is nullptr. After this operation, this |
525 // object will hold a nullptr, and will not own the object any more. | 494 // object will hold a nullptr, and will not own the object any more. |
526 element_type* release() WARN_UNUSED_RESULT { | 495 element_type* release() WARN_UNUSED_RESULT { |
527 return impl_.release(); | 496 return impl_.release(); |
528 } | 497 } |
529 | 498 |
499 // Conversion shims to help with the std::unique_ptr transition. | |
500 scoped_ptr(std::unique_ptr<T[], D>&& p) | |
dcheng
2015/11/11 16:18:34
To keep things simple, the T[] specializations jus
danakj
2015/11/14 01:29:31
Can you put that in the comment?
| |
501 : impl_(p.release(), p.get_deleter()) {} | |
502 | |
503 scoped_ptr& operator=(std::unique_ptr<T[], D>&& p) { | |
504 impl_.TakeState(&p); | |
505 return *this; | |
506 } | |
507 | |
508 operator std::unique_ptr<T[], D>() && { | |
danakj
2015/11/14 01:29:31
explain the && here too
danakj
2015/11/14 01:30:06
oops, nevermind this one.
| |
509 return std::unique_ptr<T[], D>(release(), get_deleter()); | |
510 } | |
511 | |
530 private: | 512 private: |
531 // Force element_type to be a complete type. | 513 // Force element_type to be a complete type. |
532 enum { type_must_be_complete = sizeof(element_type) }; | 514 enum { type_must_be_complete = sizeof(element_type) }; |
533 | 515 |
534 // Actually hold the data. | 516 // Actually hold the data. |
535 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_; | 517 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_; |
536 | 518 |
537 // Disable initialization from any type other than element_type*, by | 519 // Disable initialization from any type other than element_type*, by |
538 // providing a constructor that matches such an initialization, but is | 520 // providing a constructor that matches such an initialization, but is |
539 // private and has no definition. This is disabled because it is not safe to | 521 // private and has no definition. This is disabled because it is not safe to |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
578 scoped_ptr<T> make_scoped_ptr(T* ptr) { | 560 scoped_ptr<T> make_scoped_ptr(T* ptr) { |
579 return scoped_ptr<T>(ptr); | 561 return scoped_ptr<T>(ptr); |
580 } | 562 } |
581 | 563 |
582 template <typename T> | 564 template <typename T> |
583 std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) { | 565 std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) { |
584 return out << p.get(); | 566 return out << p.get(); |
585 } | 567 } |
586 | 568 |
587 #endif // BASE_MEMORY_SCOPED_PTR_H_ | 569 #endif // BASE_MEMORY_SCOPED_PTR_H_ |
OLD | NEW |