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 |