Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(333)

Side by Side Diff: base/memory/scoped_ptr.h

Issue 1440593004: Make operators on scoped_ptr match the ones defined for std::unique_ptr (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: scopedptrequals: some-more-compile-fixes Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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) {}
dcheng 2015/11/12 16:17:03 Apparently the style rule around naming parameters
danakj 2015/11/13 22:19:41 Done.
dcheng 2015/11/13 22:25:55 Another random thing I just thought of: should we
danakj 2015/11/13 22:35:23 I don't think stddef.h does the right thing (it do
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
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
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
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
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>
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;
Nico 2015/11/12 17:20:47 nit: i'd say `return p.get() == nullptr` (and for
danakj 2015/11/13 22:19:40 Done. Used .get() == nullptr here, and below I did
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 p2 < p1;
580 }
581 template <class T, class D>
582 bool operator>(const scoped_ptr<T, D>& p, std::nullptr_t n) {
583 return nullptr < p;
584 }
585 template <class T, class D>
586 bool operator>(std::nullptr_t n, const scoped_ptr<T, D>& p) {
587 return p < nullptr;
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 > p2);
593 }
594 template <class T, class D>
595 bool operator<=(const scoped_ptr<T, D>& p, std::nullptr_t n) {
596 return !(p > 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);
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 < p2);
606 }
607 template <class T, class D>
608 bool operator>=(const scoped_ptr<T, D>& p, std::nullptr_t n) {
609 return !(p < 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);
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_
OLDNEW
« no previous file with comments | « ash/wm/workspace/workspace_window_resizer_unittest.cc ('k') | base/memory/scoped_ptr_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698