| 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 using element_type = T; |
| 247 typedef D deleter_type; | 248 using deleter_type = D; |
| 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 // Note that this really should be |
| 327 // std::is_assignable, but <type_traits> |
| 328 // appears to be missing this on some |
| 329 // platforms. This is close enough (though |
| 330 // it's not the same). |
| 331 std::is_convertible<D, E>::value>::type* = |
| 332 nullptr> |
| 333 scoped_ptr& operator=(scoped_ptr<U, E>&& rhs) { |
| 290 impl_.TakeState(&rhs.impl_); | 334 impl_.TakeState(&rhs.impl_); |
| 291 return *this; | 335 return *this; |
| 292 } | 336 } |
| 293 | 337 |
| 294 // operator=. Allows assignment from a nullptr. Deletes the currently owned | 338 // operator=. Allows assignment from a nullptr. Deletes the currently owned |
| 295 // object, if any. | 339 // object, if any. |
| 296 scoped_ptr& operator=(std::nullptr_t) { | 340 scoped_ptr& operator=(std::nullptr_t) { |
| 297 reset(); | 341 reset(); |
| 298 return *this; | 342 return *this; |
| 299 } | 343 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 // Forbidden for API compatibility with std::unique_ptr. | 399 // Forbidden for API compatibility with std::unique_ptr. |
| 356 explicit scoped_ptr(int disallow_construction_from_null); | 400 explicit scoped_ptr(int disallow_construction_from_null); |
| 357 }; | 401 }; |
| 358 | 402 |
| 359 template <class T, class D> | 403 template <class T, class D> |
| 360 class scoped_ptr<T[], D> { | 404 class scoped_ptr<T[], D> { |
| 361 MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) | 405 MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) |
| 362 | 406 |
| 363 public: | 407 public: |
| 364 // The element and deleter types. | 408 // The element and deleter types. |
| 365 typedef T element_type; | 409 using element_type = T; |
| 366 typedef D deleter_type; | 410 using deleter_type = D; |
| 367 | 411 |
| 368 // Constructor. Defaults to initializing with nullptr. | 412 // Constructor. Defaults to initializing with nullptr. |
| 369 scoped_ptr() : impl_(nullptr) {} | 413 scoped_ptr() : impl_(nullptr) {} |
| 370 | 414 |
| 371 // Constructor. Stores the given array. Note that the argument's type | 415 // Constructor. Stores the given array. Note that the argument's type |
| 372 // must exactly match T*. In particular: | 416 // must exactly match T*. In particular: |
| 373 // - it cannot be a pointer to a type derived from T, because it is | 417 // - 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 | 418 // 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 | 419 // pointer whose dynamic type does not match its static type (eg., if |
| 376 // T and the derived types had different sizes access would be | 420 // 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) { | 595 scoped_ptr<T> make_scoped_ptr(T* ptr) { |
| 552 return scoped_ptr<T>(ptr); | 596 return scoped_ptr<T>(ptr); |
| 553 } | 597 } |
| 554 | 598 |
| 555 template <typename T> | 599 template <typename T> |
| 556 std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) { | 600 std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) { |
| 557 return out << p.get(); | 601 return out << p.get(); |
| 558 } | 602 } |
| 559 | 603 |
| 560 #endif // BASE_MEMORY_SCOPED_PTR_H_ | 604 #endif // BASE_MEMORY_SCOPED_PTR_H_ |
| OLD | NEW |