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 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 318 // Constructor. Defaults to initializing with nullptr. | 318 // Constructor. Defaults to initializing with nullptr. |
| 319 scoped_ptr() : impl_(nullptr) {} | 319 scoped_ptr() : impl_(nullptr) {} |
| 320 | 320 |
| 321 // Constructor. Takes ownership of p. | 321 // Constructor. Takes ownership of p. |
| 322 explicit scoped_ptr(element_type* p) : impl_(p) {} | 322 explicit scoped_ptr(element_type* p) : impl_(p) {} |
| 323 | 323 |
| 324 // Constructor. Allows initialization of a stateful deleter. | 324 // Constructor. Allows initialization of a stateful deleter. |
| 325 scoped_ptr(element_type* p, const D& d) : impl_(p, d) {} | 325 scoped_ptr(element_type* p, const D& d) : impl_(p, d) {} |
| 326 | 326 |
| 327 // Constructor. Allows construction from a nullptr. | 327 // Constructor. Allows construction from a nullptr. |
| 328 scoped_ptr(decltype(nullptr)) : impl_(nullptr) {} | 328 scoped_ptr(std::nullptr_t n) : impl_(nullptr) {} |
| 329 | 329 |
| 330 // Constructor. Allows construction from a scoped_ptr rvalue for a | 330 // Constructor. Allows construction from a scoped_ptr rvalue for a |
| 331 // convertible type and deleter. | 331 // convertible type and deleter. |
| 332 // | 332 // |
| 333 // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct | 333 // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct |
| 334 // from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor | 334 // from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor |
| 335 // has different post-conditions if D is a reference type. Since this | 335 // has different post-conditions if D is a reference type. Since this |
| 336 // implementation does not support deleters with reference type, | 336 // implementation does not support deleters with reference type, |
| 337 // we do not need a separate move constructor allowing us to avoid one | 337 // we do not need a separate move constructor allowing us to avoid one |
| 338 // use of SFINAE. You only need to care about this if you modify the | 338 // use of SFINAE. You only need to care about this if you modify the |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 355 // scoped_ptr. | 355 // scoped_ptr. |
| 356 template <typename U, typename V> | 356 template <typename U, typename V> |
| 357 scoped_ptr& operator=(scoped_ptr<U, V>&& rhs) { | 357 scoped_ptr& operator=(scoped_ptr<U, V>&& rhs) { |
| 358 COMPILE_ASSERT(!base::is_array<U>::value, U_cannot_be_an_array); | 358 COMPILE_ASSERT(!base::is_array<U>::value, U_cannot_be_an_array); |
| 359 impl_.TakeState(&rhs.impl_); | 359 impl_.TakeState(&rhs.impl_); |
| 360 return *this; | 360 return *this; |
| 361 } | 361 } |
| 362 | 362 |
| 363 // operator=. Allows assignment from a nullptr. Deletes the currently owned | 363 // operator=. Allows assignment from a nullptr. Deletes the currently owned |
| 364 // object, if any. | 364 // object, if any. |
| 365 scoped_ptr& operator=(decltype(nullptr)) { | 365 scoped_ptr& operator=(std::nullptr_t n) { |
| 366 reset(); | 366 reset(); |
| 367 return *this; | 367 return *this; |
| 368 } | 368 } |
| 369 | 369 |
| 370 // Reset. Deletes the currently owned object, if any. | 370 // Reset. Deletes the currently owned object, if any. |
| 371 // Then takes ownership of a new object, if given. | 371 // Then takes ownership of a new object, if given. |
| 372 void reset(element_type* p = nullptr) { impl_.reset(p); } | 372 void reset(element_type* p = nullptr) { impl_.reset(p); } |
| 373 | 373 |
| 374 // Accessors to get the owned object. | 374 // Accessors to get the owned object. |
| 375 // operator* and operator-> will assert() if there is no current object. | 375 // operator* and operator-> will assert() if there is no current object. |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 396 // to Testable and then do the comparison). | 396 // to Testable and then do the comparison). |
| 397 private: | 397 private: |
| 398 typedef base::internal::scoped_ptr_impl<element_type, deleter_type> | 398 typedef base::internal::scoped_ptr_impl<element_type, deleter_type> |
| 399 scoped_ptr::*Testable; | 399 scoped_ptr::*Testable; |
| 400 | 400 |
| 401 public: | 401 public: |
| 402 operator Testable() const { | 402 operator Testable() const { |
| 403 return impl_.get() ? &scoped_ptr::impl_ : nullptr; | 403 return impl_.get() ? &scoped_ptr::impl_ : nullptr; |
| 404 } | 404 } |
| 405 | 405 |
| 406 // Comparison operators. | |
| 407 // These return whether two scoped_ptr refer to the same object, not just to | |
| 408 // two different but equal objects. | |
| 409 bool operator==(const element_type* p) const { return impl_.get() == p; } | |
| 410 bool operator!=(const element_type* p) const { return impl_.get() != p; } | |
| 411 | |
| 412 // Swap two scoped pointers. | 406 // Swap two scoped pointers. |
| 413 void swap(scoped_ptr& p2) { | 407 void swap(scoped_ptr& p2) { |
| 414 impl_.swap(p2.impl_); | 408 impl_.swap(p2.impl_); |
| 415 } | 409 } |
| 416 | 410 |
| 417 // Release a pointer. | 411 // Release a pointer. |
| 418 // The return value is the current pointer held by this object. If this object | 412 // 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 | 413 // 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. | 414 // object will hold a nullptr, and will not own the object any more. |
| 421 element_type* release() WARN_UNUSED_RESULT { | 415 element_type* release() WARN_UNUSED_RESULT { |
| 422 return impl_.release(); | 416 return impl_.release(); |
| 423 } | 417 } |
| 424 | 418 |
| 425 private: | 419 private: |
| 426 // Needed to reach into |impl_| in the constructor. | 420 // Needed to reach into |impl_| in the constructor. |
| 427 template <typename U, typename V> friend class scoped_ptr; | 421 template <typename U, typename V> friend class scoped_ptr; |
| 428 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_; | 422 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_; |
| 429 | 423 |
| 430 // Forbidden for API compatibility with std::unique_ptr. | 424 // Forbidden for API compatibility with std::unique_ptr. |
| 431 explicit scoped_ptr(int disallow_construction_from_null); | 425 explicit scoped_ptr(int disallow_construction_from_null); |
| 432 | |
| 433 // 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 | |
| 435 // because you should never have the same object owned by two different | |
| 436 // scoped_ptrs. | |
| 437 template <class U> bool operator==(scoped_ptr<U> const& p2) const; | |
| 438 template <class U> bool operator!=(scoped_ptr<U> const& p2) const; | |
| 439 }; | 426 }; |
| 440 | 427 |
| 441 template <class T, class D> | 428 template <class T, class D> |
| 442 class scoped_ptr<T[], D> { | 429 class scoped_ptr<T[], D> { |
| 443 MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) | 430 MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) |
| 444 | 431 |
| 445 public: | 432 public: |
| 446 // The element and deleter types. | 433 // The element and deleter types. |
| 447 typedef T element_type; | 434 typedef T element_type; |
| 448 typedef D deleter_type; | 435 typedef D deleter_type; |
| 449 | 436 |
| 450 // Constructor. Defaults to initializing with nullptr. | 437 // Constructor. Defaults to initializing with nullptr. |
| 451 scoped_ptr() : impl_(nullptr) {} | 438 scoped_ptr() : impl_(nullptr) {} |
| 452 | 439 |
| 453 // Constructor. Stores the given array. Note that the argument's type | 440 // Constructor. Stores the given array. Note that the argument's type |
| 454 // must exactly match T*. In particular: | 441 // must exactly match T*. In particular: |
| 455 // - it cannot be a pointer to a type derived from T, because it is | 442 // - it cannot be a pointer to a type derived from T, because it is |
| 456 // inherently unsafe in the general case to access an array through a | 443 // inherently unsafe in the general case to access an array through a |
| 457 // pointer whose dynamic type does not match its static type (eg., if | 444 // pointer whose dynamic type does not match its static type (eg., if |
| 458 // T and the derived types had different sizes access would be | 445 // T and the derived types had different sizes access would be |
| 459 // incorrectly calculated). Deletion is also always undefined | 446 // incorrectly calculated). Deletion is also always undefined |
| 460 // (C++98 [expr.delete]p3). If you're doing this, fix your code. | 447 // (C++98 [expr.delete]p3). If you're doing this, fix your code. |
| 461 // - it cannot be const-qualified differently from T per unique_ptr spec | 448 // - it cannot be const-qualified differently from T per unique_ptr spec |
| 462 // (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting | 449 // (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting |
| 463 // to work around this may use const_cast<const T*>(). | 450 // to work around this may use const_cast<const T*>(). |
| 464 explicit scoped_ptr(element_type* array) : impl_(array) {} | 451 explicit scoped_ptr(element_type* array) : impl_(array) {} |
| 465 | 452 |
| 466 // Constructor. Allows construction from a nullptr. | 453 // Constructor. Allows construction from a nullptr. |
| 467 scoped_ptr(decltype(nullptr)) : impl_(nullptr) {} | 454 scoped_ptr(std::nullptr_t n) : impl_(nullptr) {} |
| 468 | 455 |
| 469 // Constructor. Allows construction from a scoped_ptr rvalue. | 456 // Constructor. Allows construction from a scoped_ptr rvalue. |
| 470 scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {} | 457 scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {} |
| 471 | 458 |
| 472 // operator=. Allows assignment from a scoped_ptr rvalue. | 459 // operator=. Allows assignment from a scoped_ptr rvalue. |
| 473 scoped_ptr& operator=(scoped_ptr&& rhs) { | 460 scoped_ptr& operator=(scoped_ptr&& rhs) { |
| 474 impl_.TakeState(&rhs.impl_); | 461 impl_.TakeState(&rhs.impl_); |
| 475 return *this; | 462 return *this; |
| 476 } | 463 } |
| 477 | 464 |
| 478 // operator=. Allows assignment from a nullptr. Deletes the currently owned | 465 // operator=. Allows assignment from a nullptr. Deletes the currently owned |
| 479 // array, if any. | 466 // array, if any. |
| 480 scoped_ptr& operator=(decltype(nullptr)) { | 467 scoped_ptr& operator=(std::nullptr_t n) { |
| 481 reset(); | 468 reset(); |
| 482 return *this; | 469 return *this; |
| 483 } | 470 } |
| 484 | 471 |
| 485 // Reset. Deletes the currently owned array, if any. | 472 // Reset. Deletes the currently owned array, if any. |
| 486 // Then takes ownership of a new object, if given. | 473 // Then takes ownership of a new object, if given. |
| 487 void reset(element_type* array = nullptr) { impl_.reset(array); } | 474 void reset(element_type* array = nullptr) { impl_.reset(array); } |
| 488 | 475 |
| 489 // Accessors to get the owned array. | 476 // Accessors to get the owned array. |
| 490 element_type& operator[](size_t i) const { | 477 element_type& operator[](size_t i) const { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 501 // implicitly convertible to a real bool (which is dangerous). | 488 // implicitly convertible to a real bool (which is dangerous). |
| 502 private: | 489 private: |
| 503 typedef base::internal::scoped_ptr_impl<element_type, deleter_type> | 490 typedef base::internal::scoped_ptr_impl<element_type, deleter_type> |
| 504 scoped_ptr::*Testable; | 491 scoped_ptr::*Testable; |
| 505 | 492 |
| 506 public: | 493 public: |
| 507 operator Testable() const { | 494 operator Testable() const { |
| 508 return impl_.get() ? &scoped_ptr::impl_ : nullptr; | 495 return impl_.get() ? &scoped_ptr::impl_ : nullptr; |
| 509 } | 496 } |
| 510 | 497 |
| 511 // Comparison operators. | |
| 512 // These return whether two scoped_ptr refer to the same object, not just to | |
| 513 // two different but equal objects. | |
| 514 bool operator==(element_type* array) const { return impl_.get() == array; } | |
| 515 bool operator!=(element_type* array) const { return impl_.get() != array; } | |
| 516 | |
| 517 // Swap two scoped pointers. | 498 // Swap two scoped pointers. |
| 518 void swap(scoped_ptr& p2) { | 499 void swap(scoped_ptr& p2) { |
| 519 impl_.swap(p2.impl_); | 500 impl_.swap(p2.impl_); |
| 520 } | 501 } |
| 521 | 502 |
| 522 // Release a pointer. | 503 // Release a pointer. |
| 523 // The return value is the current pointer held by this object. If this object | 504 // 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 | 505 // 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. | 506 // object will hold a nullptr, and will not own the object any more. |
| 526 element_type* release() WARN_UNUSED_RESULT { | 507 element_type* release() WARN_UNUSED_RESULT { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 539 // private and has no definition. This is disabled because it is not safe to | 520 // private and has no definition. This is disabled because it is not safe to |
| 540 // call delete[] on an array whose static type does not match its dynamic | 521 // call delete[] on an array whose static type does not match its dynamic |
| 541 // type. | 522 // type. |
| 542 template <typename U> explicit scoped_ptr(U* array); | 523 template <typename U> explicit scoped_ptr(U* array); |
| 543 explicit scoped_ptr(int disallow_construction_from_null); | 524 explicit scoped_ptr(int disallow_construction_from_null); |
| 544 | 525 |
| 545 // Disable reset() from any type other than element_type*, for the same | 526 // Disable reset() from any type other than element_type*, for the same |
| 546 // reasons as the constructor above. | 527 // reasons as the constructor above. |
| 547 template <typename U> void reset(U* array); | 528 template <typename U> void reset(U* array); |
| 548 void reset(int disallow_reset_from_null); | 529 void reset(int disallow_reset_from_null); |
| 549 | |
| 550 // Forbid comparison of scoped_ptr types. If U != T, it totally | |
| 551 // doesn't make sense, and if U == T, it still doesn't make sense | |
| 552 // because you should never have the same object owned by two different | |
| 553 // scoped_ptrs. | |
| 554 template <class U> bool operator==(scoped_ptr<U> const& p2) const; | |
| 555 template <class U> bool operator!=(scoped_ptr<U> const& p2) const; | |
| 556 }; | 530 }; |
| 557 | 531 |
| 558 // Free functions | 532 // Free functions |
| 559 template <class T, class D> | 533 template <class T, class D> |
| 560 void swap(scoped_ptr<T, D>& p1, scoped_ptr<T, D>& p2) { | 534 void swap(scoped_ptr<T, D>& p1, scoped_ptr<T, D>& p2) { |
| 561 p1.swap(p2); | 535 p1.swap(p2); |
| 562 } | 536 } |
| 563 | 537 |
| 538 template <class T1, class D1, class T2, class D2> | |
|
danakj
2015/11/11 20:38:36
Here are the libcxx implementations of these opera
| |
| 539 bool operator==(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) { | |
| 540 return p1.get() == p2.get(); | |
| 541 } | |
| 564 template <class T, class D> | 542 template <class T, class D> |
| 565 bool operator==(T* p1, const scoped_ptr<T, D>& p2) { | 543 bool operator==(const scoped_ptr<T, D>& p, std::nullptr_t n) { |
| 566 return p1 == p2.get(); | 544 return !p; |
| 545 } | |
| 546 template <class T, class D> | |
| 547 bool operator==(std::nullptr_t n, const scoped_ptr<T, D>& p) { | |
| 548 return !p; | |
| 567 } | 549 } |
| 568 | 550 |
| 551 template <class T1, class D1, class T2, class D2> | |
| 552 bool operator!=(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) { | |
| 553 return !(p1 == p2); | |
| 554 } | |
| 569 template <class T, class D> | 555 template <class T, class D> |
| 570 bool operator!=(T* p1, const scoped_ptr<T, D>& p2) { | 556 bool operator!=(const scoped_ptr<T, D>& p, std::nullptr_t n) { |
| 571 return p1 != p2.get(); | 557 return !!p; |
| 558 } | |
| 559 template <class T, class D> | |
| 560 bool operator!=(std::nullptr_t n, const scoped_ptr<T, D>& p) { | |
| 561 return !!p; | |
| 562 } | |
| 563 | |
| 564 template <class T1, class D1, class T2, class D2> | |
| 565 bool operator<(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) { | |
| 566 return p1.get() < p2.get(); | |
| 567 } | |
| 568 template <class T, class D> | |
| 569 bool operator<(const scoped_ptr<T, D>& p, std::nullptr_t n) { | |
| 570 return p.get() < nullptr; | |
| 571 } | |
| 572 template <class T, class D> | |
| 573 bool operator<(std::nullptr_t n, const scoped_ptr<T, D>& p) { | |
| 574 return nullptr < p.get(); | |
| 575 } | |
| 576 | |
| 577 template <class T1, class D1, class T2, class D2> | |
| 578 bool operator>(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) { | |
| 579 return p1.get() > p2.get(); | |
|
dcheng
2015/11/11 20:55:06
Not necessary, but it can be nice to express these
danakj
2015/11/11 21:01:15
yup good idea. done. also wrote a bug and realized
| |
| 580 } | |
| 581 template <class T, class D> | |
| 582 bool operator>(const scoped_ptr<T, D>& p, std::nullptr_t n) { | |
| 583 return p.get() > nullptr; | |
| 584 } | |
| 585 template <class T, class D> | |
| 586 bool operator>(std::nullptr_t n, const scoped_ptr<T, D>& p) { | |
| 587 return nullptr > p.get(); | |
| 588 } | |
| 589 | |
| 590 template <class T1, class D1, class T2, class D2> | |
| 591 bool operator<=(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) { | |
| 592 return !(p1.get() > p2.get()); | |
| 593 } | |
| 594 template <class T, class D> | |
| 595 bool operator<=(const scoped_ptr<T, D>& p, std::nullptr_t n) { | |
| 596 return !(p.get() > nullptr); | |
| 597 } | |
| 598 template <class T, class D> | |
| 599 bool operator<=(std::nullptr_t n, const scoped_ptr<T, D>& p) { | |
| 600 return !(nullptr > p.get()); | |
| 601 } | |
| 602 | |
| 603 template <class T1, class D1, class T2, class D2> | |
| 604 bool operator>=(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) { | |
| 605 return !(p1.get() < p2.get()); | |
| 606 } | |
| 607 template <class T, class D> | |
| 608 bool operator>=(const scoped_ptr<T, D>& p, std::nullptr_t n) { | |
| 609 return !(p.get() < nullptr); | |
| 610 } | |
| 611 template <class T, class D> | |
| 612 bool operator>=(std::nullptr_t n, const scoped_ptr<T, D>& p) { | |
| 613 return !(nullptr < p.get()); | |
| 572 } | 614 } |
| 573 | 615 |
| 574 // A function to convert T* into scoped_ptr<T> | 616 // A function to convert T* into scoped_ptr<T> |
| 575 // Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation | 617 // Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation |
| 576 // for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg)) | 618 // for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg)) |
| 577 template <typename T> | 619 template <typename T> |
| 578 scoped_ptr<T> make_scoped_ptr(T* ptr) { | 620 scoped_ptr<T> make_scoped_ptr(T* ptr) { |
| 579 return scoped_ptr<T>(ptr); | 621 return scoped_ptr<T>(ptr); |
| 580 } | 622 } |
| 581 | 623 |
| 582 template <typename T> | 624 template <typename T> |
| 583 std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) { | 625 std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) { |
| 584 return out << p.get(); | 626 return out << p.get(); |
| 585 } | 627 } |
| 586 | 628 |
| 587 #endif // BASE_MEMORY_SCOPED_PTR_H_ | 629 #endif // BASE_MEMORY_SCOPED_PTR_H_ |
| OLD | NEW |