Chromium Code Reviews| 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 <iosfwd> | 87 #include <iosfwd> |
| 88 #include <memory> | 88 #include <memory> |
| 89 #include <type_traits> | |
| 89 #include <utility> | 90 #include <utility> |
| 90 | 91 |
| 91 #include "base/basictypes.h" | 92 #include "base/basictypes.h" |
| 92 #include "base/compiler_specific.h" | 93 #include "base/compiler_specific.h" |
| 93 #include "base/move.h" | 94 #include "base/move.h" |
| 94 #include "base/template_util.h" | 95 #include "base/template_util.h" |
| 95 | 96 |
| 96 namespace base { | 97 namespace base { |
| 97 | 98 |
| 98 namespace subtle { | 99 namespace subtle { |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 236 // types. | 237 // types. |
| 237 template <class T, class D = std::default_delete<T>> | 238 template <class T, class D = std::default_delete<T>> |
| 238 class scoped_ptr { | 239 class scoped_ptr { |
| 239 MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) | 240 MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) |
| 240 | 241 |
| 241 COMPILE_ASSERT(base::internal::IsNotRefCounted<T>::value, | 242 COMPILE_ASSERT(base::internal::IsNotRefCounted<T>::value, |
| 242 T_is_refcounted_type_and_needs_scoped_refptr); | 243 T_is_refcounted_type_and_needs_scoped_refptr); |
| 243 | 244 |
| 244 public: | 245 public: |
| 245 // The element and deleter types. | 246 // The element and deleter types. |
| 246 typedef T element_type; | 247 typedef T element_type; |
|
danakj
2015/11/19 21:31:11
using here too while you're at it? :)
dcheng
2015/11/19 21:39:45
Done.
| |
| 247 typedef D deleter_type; | 248 typedef D deleter_type; |
| 248 | 249 |
| 249 // Constructor. Defaults to initializing with nullptr. | 250 // Constructor. Defaults to initializing with nullptr. |
| 250 scoped_ptr() : impl_(nullptr) {} | 251 scoped_ptr() : impl_(nullptr) {} |
| 251 | 252 |
| 252 // Constructor. Takes ownership of p. | 253 // Constructor. Takes ownership of p. |
| 253 explicit scoped_ptr(element_type* p) : impl_(p) {} | 254 explicit scoped_ptr(element_type* p) : impl_(p) {} |
| 254 | 255 |
| 255 // Constructor. Allows initialization of a stateful deleter. | 256 // Constructor. Allows initialization of a stateful deleter. |
| 256 scoped_ptr(element_type* p, const D& d) : impl_(p, d) {} | 257 scoped_ptr(element_type* p, const D& d) : impl_(p, d) {} |
| 257 | 258 |
| 258 // Constructor. Allows construction from a nullptr. | 259 // Constructor. Allows construction from a nullptr. |
| 259 scoped_ptr(std::nullptr_t) : impl_(nullptr) {} | 260 scoped_ptr(std::nullptr_t) : impl_(nullptr) {} |
| 260 | 261 |
| 261 // Constructor. Allows construction from a scoped_ptr rvalue for a | 262 // Move constructor. |
| 263 // | |
| 264 // IMPLEMENTATION NOTE: Clang requires a move constructor to be defined (and | |
| 265 // not just the conversion constructor) in order to warn on pessimizing moves. | |
| 266 // The requirements for the move constructor are specified in C++11 | |
| 267 // 20.7.1.2.1.15-17, which has some subtleties around reference deleters. As | |
| 268 // we don't support reference (or move-only) deleters, the post conditions are | |
| 269 // trivially true: we always copy construct the deleter from other's deleter. | |
| 270 scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {} | |
| 271 | |
| 272 // Conversion constructor. Allows construction from a scoped_ptr rvalue for a | |
| 262 // convertible type and deleter. | 273 // convertible type and deleter. |
| 263 // | 274 // |
| 264 // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct | 275 // IMPLEMENTATION NOTE: C++ 20.7.1.2.1.19 requires this constructor to only |
| 265 // from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor | 276 // participate in overload resolution if all the following are true: |
| 266 // has different post-conditions if D is a reference type. Since this | 277 // - U is implicitly convertible to T: this is important for 2 reasons: |
| 267 // implementation does not support deleters with reference type, | 278 // 1. So type traits don't incorrectly return true, e.g. |
| 268 // we do not need a separate move constructor allowing us to avoid one | 279 // std::is_convertible<scoped_ptr<Base>, scoped_ptr<Derived>>::value |
| 269 // use of SFINAE. You only need to care about this if you modify the | 280 // should be false. |
| 270 // implementation of scoped_ptr. | 281 // 2. To make sure code like this compiles: |
| 271 template <typename U, typename V> | 282 // void F(scoped_ptr<int>); |
| 272 scoped_ptr(scoped_ptr<U, V>&& other) | 283 // void F(scoped_ptr<Base>); |
| 273 : impl_(&other.impl_) { | 284 // // Ambiguous since both conversion constructors match. |
| 274 COMPILE_ASSERT(!base::is_array<U>::value, U_cannot_be_an_array); | 285 // F(scoped_ptr<Derived>()); |
| 286 // - U is not an array type: to prevent conversions from scoped_ptr<T[]> to | |
| 287 // scoped_ptr<T>. | |
| 288 // - D is a reference type and E is the same type, or D is not a reference | |
| 289 // type and E is implicitly convertible to D: again, we don't support | |
| 290 // reference deleters, so we only worry about the latter requirement. | |
| 291 template <typename U, | |
| 292 typename E, | |
| 293 typename std::enable_if<!std::is_array<U>::value && | |
| 294 std::is_convertible<U*, T*>::value && | |
| 295 std::is_convertible<E, D>::value>::type* = | |
| 296 nullptr> | |
| 297 scoped_ptr(scoped_ptr<U, E>&& other) | |
| 298 : impl_(&other.impl_) {} | |
| 299 | |
| 300 // operator=. | |
| 301 // | |
| 302 // IMPLEMENTATION NOTE: Unlike the move constructor, Clang does not appear to | |
| 303 // require a move assignment operator to trigger the pessimizing move warning: | |
| 304 // in this case, the warning triggers when moving a temporary. For consistency | |
| 305 // with the move constructor, we define it anyway. C++11 20.7.1.2.3.1-3 | |
| 306 // defines several requirements around this: like the move constructor, the | |
| 307 // requirements are simplified by the fact that we don't support move-only or | |
| 308 // reference deleters. | |
| 309 scoped_ptr& operator=(scoped_ptr&& rhs) { | |
| 310 impl_.TakeState(&rhs.impl_); | |
| 311 return *this; | |
| 275 } | 312 } |
| 276 | 313 |
| 277 // operator=. Allows assignment from a scoped_ptr rvalue for a convertible | 314 // operator=. Allows assignment from a scoped_ptr rvalue for a convertible |
| 278 // type and deleter. | 315 // type and deleter. |
| 279 // | 316 // |
| 280 // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from | 317 // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from |
| 281 // the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated | 318 // the normal move assignment operator. C++11 20.7.1.2.3.4-7 contains the |
| 282 // form has different requirements on for move-only Deleters. Since this | 319 // requirement for this operator, but like the conversion constructor, the |
| 283 // implementation does not support move-only Deleters, we do not need a | 320 // requirements are greatly simplified by not supporting move-only or |
| 284 // separate move assignment operator allowing us to avoid one use of SFINAE. | 321 // reference deleters. |
| 285 // You only need to care about this if you modify the implementation of | 322 template <typename U, |
| 286 // scoped_ptr. | 323 typename E, |
| 287 template <typename U, typename V> | 324 typename std::enable_if<!std::is_array<U>::value && |
| 288 scoped_ptr& operator=(scoped_ptr<U, V>&& rhs) { | 325 std::is_convertible<U*, T*>::value && |
| 289 COMPILE_ASSERT(!base::is_array<U>::value, U_cannot_be_an_array); | 326 std::is_convertible<E, D>::value>::type* = |
|
danakj
2015/11/19 21:31:11
This should be is_assignable here for the deleter
dcheng
2015/11/19 21:39:45
Done.
| |
| 327 nullptr> | |
| 328 scoped_ptr& operator=(scoped_ptr<U, E>&& rhs) { | |
| 290 impl_.TakeState(&rhs.impl_); | 329 impl_.TakeState(&rhs.impl_); |
| 291 return *this; | 330 return *this; |
| 292 } | 331 } |
| 293 | 332 |
| 294 // operator=. Allows assignment from a nullptr. Deletes the currently owned | 333 // operator=. Allows assignment from a nullptr. Deletes the currently owned |
| 295 // object, if any. | 334 // object, if any. |
| 296 scoped_ptr& operator=(std::nullptr_t) { | 335 scoped_ptr& operator=(std::nullptr_t) { |
| 297 reset(); | 336 reset(); |
| 298 return *this; | 337 return *this; |
| 299 } | 338 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 355 // Forbidden for API compatibility with std::unique_ptr. | 394 // Forbidden for API compatibility with std::unique_ptr. |
| 356 explicit scoped_ptr(int disallow_construction_from_null); | 395 explicit scoped_ptr(int disallow_construction_from_null); |
| 357 }; | 396 }; |
| 358 | 397 |
| 359 template <class T, class D> | 398 template <class T, class D> |
| 360 class scoped_ptr<T[], D> { | 399 class scoped_ptr<T[], D> { |
| 361 MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) | 400 MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) |
| 362 | 401 |
| 363 public: | 402 public: |
| 364 // The element and deleter types. | 403 // The element and deleter types. |
| 365 typedef T element_type; | 404 using element_type = T; |
| 366 typedef D deleter_type; | 405 using deleter_type = D; |
| 367 | 406 |
| 368 // Constructor. Defaults to initializing with nullptr. | 407 // Constructor. Defaults to initializing with nullptr. |
| 369 scoped_ptr() : impl_(nullptr) {} | 408 scoped_ptr() : impl_(nullptr) {} |
| 370 | 409 |
| 371 // Constructor. Stores the given array. Note that the argument's type | 410 // Constructor. Stores the given array. Note that the argument's type |
| 372 // must exactly match T*. In particular: | 411 // must exactly match T*. In particular: |
| 373 // - it cannot be a pointer to a type derived from T, because it is | 412 // - it cannot be a pointer to a type derived from T, because it is |
| 374 // inherently unsafe in the general case to access an array through a | 413 // inherently unsafe in the general case to access an array through a |
| 375 // pointer whose dynamic type does not match its static type (eg., if | 414 // pointer whose dynamic type does not match its static type (eg., if |
| 376 // T and the derived types had different sizes access would be | 415 // T and the derived types had different sizes access would be |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 551 scoped_ptr<T> make_scoped_ptr(T* ptr) { | 590 scoped_ptr<T> make_scoped_ptr(T* ptr) { |
| 552 return scoped_ptr<T>(ptr); | 591 return scoped_ptr<T>(ptr); |
| 553 } | 592 } |
| 554 | 593 |
| 555 template <typename T> | 594 template <typename T> |
| 556 std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) { | 595 std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) { |
| 557 return out << p.get(); | 596 return out << p.get(); |
| 558 } | 597 } |
| 559 | 598 |
| 560 #endif // BASE_MEMORY_SCOPED_PTR_H_ | 599 #endif // BASE_MEMORY_SCOPED_PTR_H_ |
| OLD | NEW |