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

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

Issue 1801823003: Remove legacy scoped_ptr implementation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Restore operators Created 4 years, 9 months 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
« no previous file with comments | « base/base.gyp ('k') | base/memory/scoped_ptr_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 // 83 //
84 // scoped_ptr<Foo> foo(new Foo()); 84 // scoped_ptr<Foo> foo(new Foo());
85 // scoped_ptr<FooParent> parent(std::move(foo)); 85 // scoped_ptr<FooParent> parent(std::move(foo));
86 86
87 #ifndef BASE_MEMORY_SCOPED_PTR_H_ 87 #ifndef BASE_MEMORY_SCOPED_PTR_H_
88 #define BASE_MEMORY_SCOPED_PTR_H_ 88 #define BASE_MEMORY_SCOPED_PTR_H_
89 89
90 // This is an implementation designed to match the anticipated future TR2 90 // This is an implementation designed to match the anticipated future TR2
91 // implementation of the scoped_ptr class. 91 // implementation of the scoped_ptr class.
92 92
93 // TODO(dcheng): Clean up these headers, but there are likely lots of existing
94 // IWYU violations.
93 #include <stddef.h> 95 #include <stddef.h>
94 #include <stdlib.h> 96 #include <stdlib.h>
95 97
96 #include <iosfwd> 98 #include <iosfwd>
97 #include <memory> 99 #include <memory>
98 #include <type_traits> 100 #include <type_traits>
99 #include <utility> 101 #include <utility>
100 102
101 #include "base/compiler_specific.h" 103 #include "base/compiler_specific.h"
102 #include "base/logging.h" 104 #include "base/logging.h"
103 #include "base/macros.h" 105 #include "base/macros.h"
104 #include "base/move.h" 106 #include "base/move.h"
105 #include "build/build_config.h" 107 #include "build/build_config.h"
106 108
107 namespace base { 109 namespace base {
108 110
109 // Function object which invokes 'free' on its parameter, which must be 111 // Function object which invokes 'free' on its parameter, which must be
110 // a pointer. Can be used to store malloc-allocated pointers in scoped_ptr: 112 // a pointer. Can be used to store malloc-allocated pointers in scoped_ptr:
111 // 113 //
112 // scoped_ptr<int, base::FreeDeleter> foo_ptr( 114 // scoped_ptr<int, base::FreeDeleter> foo_ptr(
113 // static_cast<int*>(malloc(sizeof(int)))); 115 // static_cast<int*>(malloc(sizeof(int))));
114 struct FreeDeleter { 116 struct FreeDeleter {
115 inline void operator()(void* ptr) const { 117 inline void operator()(void* ptr) const {
116 free(ptr); 118 free(ptr);
117 } 119 }
118 }; 120 };
119 121
120 } // namespace base 122 } // namespace base
121 123
122 // Now that scoped_ptr is almost 100% compatible with std::unique_ptr, we're
123 // incrementally migrating scoped_ptr to just be a type alias for
124 // std::unique_ptr. The eventual goal is to delete scoped_ptr altogether.
125 #if defined(OS_LINUX) || defined(OS_WIN) || defined(OS_ANDROID) || \
126 defined(OS_MACOSX)
127 template <typename T, typename D = std::default_delete<T>> 124 template <typename T, typename D = std::default_delete<T>>
128 using scoped_ptr = std::unique_ptr<T, D>; 125 using scoped_ptr = std::unique_ptr<T, D>;
129 126
130 // Versions of libstdc++ 4.8 lack overloads for <, <=, >, and >= when comparing 127 // Versions of libstdc++ 4.8 lack overloads for <, <=, >, and >= when comparing
131 // a std::unique_ptr and nullptr_t. 128 // a std::unique_ptr and nullptr_t.
132 #if defined(__GLIBCXX__) && __GLIBCXX__ < 20150123 129 #if defined(__GLIBCXX__) && __GLIBCXX__ < 20150123
133 template <class T, class D> 130 template <class T, class D>
134 bool operator<(const scoped_ptr<T, D>& p, std::nullptr_t) { 131 bool operator<(const scoped_ptr<T, D>& p, std::nullptr_t) {
135 return p.get() < nullptr; 132 return p.get() < nullptr;
136 } 133 }
(...skipping 21 matching lines...) Expand all
158 } 155 }
159 156
160 template <class T, class D> 157 template <class T, class D>
161 bool operator>=(const scoped_ptr<T, D>& p, std::nullptr_t) { 158 bool operator>=(const scoped_ptr<T, D>& p, std::nullptr_t) {
162 return !(p < nullptr); 159 return !(p < nullptr);
163 } 160 }
164 template <class T, class D> 161 template <class T, class D>
165 bool operator>=(std::nullptr_t, const scoped_ptr<T, D>& p) { 162 bool operator>=(std::nullptr_t, const scoped_ptr<T, D>& p) {
166 return !(nullptr < p); 163 return !(nullptr < p);
167 } 164 }
168 #endif // defined(__GLIBCXX__) && __GLIBCX__ < 20150426 165 #endif // defined(__GLIBCXX__) && __GLIBCXX__ < 20150123
169
170 #else
171 namespace base {
172
173 namespace subtle {
174 class RefCountedBase;
175 class RefCountedThreadSafeBase;
176 } // namespace subtle
177
178 namespace internal {
179
180 template <typename T> struct IsNotRefCounted {
181 enum {
182 value = !std::is_convertible<T*, base::subtle::RefCountedBase*>::value &&
183 !std::is_convertible<T*, base::subtle::RefCountedThreadSafeBase*>::
184 value
185 };
186 };
187
188 // Minimal implementation of the core logic of scoped_ptr, suitable for
189 // reuse in both scoped_ptr and its specializations.
190 template <class T, class D>
191 class scoped_ptr_impl {
192 public:
193 explicit scoped_ptr_impl(T* p) : data_(p) {}
194
195 // Initializer for deleters that have data parameters.
196 scoped_ptr_impl(T* p, const D& d) : data_(p, d) {}
197
198 // Templated constructor that destructively takes the value from another
199 // scoped_ptr_impl.
200 template <typename U, typename V>
201 scoped_ptr_impl(scoped_ptr_impl<U, V>* other)
202 : data_(other->release(), other->get_deleter()) {
203 // We do not support move-only deleters. We could modify our move
204 // emulation to have base::subtle::move() and base::subtle::forward()
205 // functions that are imperfect emulations of their C++11 equivalents,
206 // but until there's a requirement, just assume deleters are copyable.
207 }
208
209 template <typename U, typename V>
210 void TakeState(scoped_ptr_impl<U, V>* other) {
211 // See comment in templated constructor above regarding lack of support
212 // for move-only deleters.
213 reset(other->release());
214 get_deleter() = other->get_deleter();
215 }
216
217 ~scoped_ptr_impl() {
218 // Match libc++, which calls reset() in its destructor.
219 // Use nullptr as the new value for three reasons:
220 // 1. libc++ does it.
221 // 2. Avoids infinitely recursing into destructors if two classes are owned
222 // in a reference cycle (see ScopedPtrTest.ReferenceCycle).
223 // 3. If |this| is accessed in the future, in a use-after-free bug, attempts
224 // to dereference |this|'s pointer should cause either a failure or a
225 // segfault closer to the problem. If |this| wasn't reset to nullptr,
226 // the access would cause the deleted memory to be read or written
227 // leading to other more subtle issues.
228 reset(nullptr);
229 }
230
231 void reset(T* p) {
232 // Match C++11's definition of unique_ptr::reset(), which requires changing
233 // the pointer before invoking the deleter on the old pointer. This prevents
234 // |this| from being accessed after the deleter is run, which may destroy
235 // |this|.
236 T* old = data_.ptr;
237 data_.ptr = p;
238 if (old != nullptr)
239 static_cast<D&>(data_)(old);
240 }
241
242 T* get() const { return data_.ptr; }
243
244 D& get_deleter() { return data_; }
245 const D& get_deleter() const { return data_; }
246
247 void swap(scoped_ptr_impl& p2) {
248 // Standard swap idiom: 'using std::swap' ensures that std::swap is
249 // present in the overload set, but we call swap unqualified so that
250 // any more-specific overloads can be used, if available.
251 using std::swap;
252 swap(static_cast<D&>(data_), static_cast<D&>(p2.data_));
253 swap(data_.ptr, p2.data_.ptr);
254 }
255
256 T* release() {
257 T* old_ptr = data_.ptr;
258 data_.ptr = nullptr;
259 return old_ptr;
260 }
261
262 private:
263 // Needed to allow type-converting constructor.
264 template <typename U, typename V> friend class scoped_ptr_impl;
265
266 // Use the empty base class optimization to allow us to have a D
267 // member, while avoiding any space overhead for it when D is an
268 // empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good
269 // discussion of this technique.
270 struct Data : public D {
271 explicit Data(T* ptr_in) : ptr(ptr_in) {}
272 Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {}
273 T* ptr;
274 };
275
276 Data data_;
277
278 DISALLOW_COPY_AND_ASSIGN(scoped_ptr_impl);
279 };
280
281 } // namespace internal
282
283 } // namespace base
284
285 // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
286 // automatically deletes the pointer it holds (if any).
287 // That is, scoped_ptr<T> owns the T object that it points to.
288 // Like a T*, a scoped_ptr<T> may hold either nullptr or a pointer to a T
289 // object. Also like T*, scoped_ptr<T> is thread-compatible, and once you
290 // dereference it, you get the thread safety guarantees of T.
291 //
292 // The size of scoped_ptr is small. On most compilers, when using the
293 // std::default_delete, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters
294 // will increase the size proportional to whatever state they need to have. See
295 // comments inside scoped_ptr_impl<> for details.
296 //
297 // Current implementation targets having a strict subset of C++11's
298 // unique_ptr<> features. Known deficiencies include not supporting move-only
299 // deleteres, function pointers as deleters, and deleters with reference
300 // types.
301 template <class T, class D = std::default_delete<T>>
302 class scoped_ptr {
303 DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(scoped_ptr)
304
305 static_assert(!std::is_array<T>::value,
306 "scoped_ptr doesn't support array with size");
307 static_assert(base::internal::IsNotRefCounted<T>::value,
308 "T is a refcounted type and needs a scoped_refptr");
309
310 public:
311 // The element and deleter types.
312 using element_type = T;
313 using deleter_type = D;
314
315 // Constructor. Defaults to initializing with nullptr.
316 scoped_ptr() : impl_(nullptr) {}
317
318 // Constructor. Takes ownership of p.
319 explicit scoped_ptr(element_type* p) : impl_(p) {}
320
321 // Constructor. Allows initialization of a stateful deleter.
322 scoped_ptr(element_type* p, const D& d) : impl_(p, d) {}
323
324 // Constructor. Allows construction from a nullptr.
325 scoped_ptr(std::nullptr_t) : impl_(nullptr) {}
326
327 // Move constructor.
328 //
329 // IMPLEMENTATION NOTE: Clang requires a move constructor to be defined (and
330 // not just the conversion constructor) in order to warn on pessimizing moves.
331 // The requirements for the move constructor are specified in C++11
332 // 20.7.1.2.1.15-17, which has some subtleties around reference deleters. As
333 // we don't support reference (or move-only) deleters, the post conditions are
334 // trivially true: we always copy construct the deleter from other's deleter.
335 scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {}
336
337 // Conversion constructor. Allows construction from a scoped_ptr rvalue for a
338 // convertible type and deleter.
339 //
340 // IMPLEMENTATION NOTE: C++ 20.7.1.2.1.19 requires this constructor to only
341 // participate in overload resolution if all the following are true:
342 // - U is implicitly convertible to T: this is important for 2 reasons:
343 // 1. So type traits don't incorrectly return true, e.g.
344 // std::is_convertible<scoped_ptr<Base>, scoped_ptr<Derived>>::value
345 // should be false.
346 // 2. To make sure code like this compiles:
347 // void F(scoped_ptr<int>);
348 // void F(scoped_ptr<Base>);
349 // // Ambiguous since both conversion constructors match.
350 // F(scoped_ptr<Derived>());
351 // - U is not an array type: to prevent conversions from scoped_ptr<T[]> to
352 // scoped_ptr<T>.
353 // - D is a reference type and E is the same type, or D is not a reference
354 // type and E is implicitly convertible to D: again, we don't support
355 // reference deleters, so we only worry about the latter requirement.
356 template <typename U,
357 typename E,
358 typename std::enable_if<!std::is_array<U>::value &&
359 std::is_convertible<U*, T*>::value &&
360 std::is_convertible<E, D>::value>::type* =
361 nullptr>
362 scoped_ptr(scoped_ptr<U, E>&& other)
363 : impl_(&other.impl_) {}
364
365 // operator=.
366 //
367 // IMPLEMENTATION NOTE: Unlike the move constructor, Clang does not appear to
368 // require a move assignment operator to trigger the pessimizing move warning:
369 // in this case, the warning triggers when moving a temporary. For consistency
370 // with the move constructor, we define it anyway. C++11 20.7.1.2.3.1-3
371 // defines several requirements around this: like the move constructor, the
372 // requirements are simplified by the fact that we don't support move-only or
373 // reference deleters.
374 scoped_ptr& operator=(scoped_ptr&& rhs) {
375 impl_.TakeState(&rhs.impl_);
376 return *this;
377 }
378
379 // operator=. Allows assignment from a scoped_ptr rvalue for a convertible
380 // type and deleter.
381 //
382 // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from
383 // the normal move assignment operator. C++11 20.7.1.2.3.4-7 contains the
384 // requirement for this operator, but like the conversion constructor, the
385 // requirements are greatly simplified by not supporting move-only or
386 // reference deleters.
387 template <typename U,
388 typename E,
389 typename std::enable_if<!std::is_array<U>::value &&
390 std::is_convertible<U*, T*>::value &&
391 // Note that this really should be
392 // std::is_assignable, but <type_traits>
393 // appears to be missing this on some
394 // platforms. This is close enough (though
395 // it's not the same).
396 std::is_convertible<D, E>::value>::type* =
397 nullptr>
398 scoped_ptr& operator=(scoped_ptr<U, E>&& rhs) {
399 impl_.TakeState(&rhs.impl_);
400 return *this;
401 }
402
403 // operator=. Allows assignment from a nullptr. Deletes the currently owned
404 // object, if any.
405 scoped_ptr& operator=(std::nullptr_t) {
406 reset();
407 return *this;
408 }
409
410 // Reset. Deletes the currently owned object, if any.
411 // Then takes ownership of a new object, if given.
412 void reset(element_type* p = nullptr) { impl_.reset(p); }
413
414 // Accessors to get the owned object.
415 // operator* and operator-> will DCHECK() if there is no current object.
416 element_type& operator*() const {
417 DCHECK(impl_.get() != nullptr);
418 return *impl_.get();
419 }
420 element_type* operator->() const {
421 DCHECK(impl_.get() != nullptr);
422 return impl_.get();
423 }
424 element_type* get() const { return impl_.get(); }
425
426 // Access to the deleter.
427 deleter_type& get_deleter() { return impl_.get_deleter(); }
428 const deleter_type& get_deleter() const { return impl_.get_deleter(); }
429
430 // Implement "Safe Bool Idiom"
431 // https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Safe_bool
432 //
433 // Allow scoped_ptr<element_type> to be used in boolean expressions such as
434 // if (scoped_ptr_instance)
435 // But do not become convertible to a real bool (which is dangerous).
436 // Implementation requires:
437 // typedef Testable
438 // operator Testable() const
439 // operator==
440 // operator!=
441 //
442 // == and != operators must be declared explicitly or dissallowed, as
443 // otherwise "ptr1 == ptr2" will compile but do the wrong thing (i.e., convert
444 // to Testable and then do the comparison).
445 //
446 // C++11 provides for "explicit operator bool()", however it is currently
447 // banned due to MSVS2013. https://chromium-cpp.appspot.com/#core-blacklist
448 private:
449 typedef base::internal::scoped_ptr_impl<element_type, deleter_type>
450 scoped_ptr::*Testable;
451 public:
452 operator Testable() const {
453 return impl_.get() ? &scoped_ptr::impl_ : nullptr;
454 }
455
456 // Swap two scoped pointers.
457 void swap(scoped_ptr& p2) {
458 impl_.swap(p2.impl_);
459 }
460
461 // Release a pointer.
462 // The return value is the current pointer held by this object. If this object
463 // holds a nullptr, the return value is nullptr. After this operation, this
464 // object will hold a nullptr, and will not own the object any more.
465 element_type* release() WARN_UNUSED_RESULT {
466 return impl_.release();
467 }
468
469 private:
470 // Needed to reach into |impl_| in the constructor.
471 template <typename U, typename V> friend class scoped_ptr;
472 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
473
474 // Forbidden for API compatibility with std::unique_ptr.
475 explicit scoped_ptr(int disallow_construction_from_null);
476 };
477
478 template <class T, class D>
479 class scoped_ptr<T[], D> {
480 DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(scoped_ptr)
481
482 public:
483 // The element and deleter types.
484 using element_type = T;
485 using deleter_type = D;
486
487 // Constructor. Defaults to initializing with nullptr.
488 scoped_ptr() : impl_(nullptr) {}
489
490 // Constructor. Stores the given array. Note that the argument's type
491 // must exactly match T*. In particular:
492 // - it cannot be a pointer to a type derived from T, because it is
493 // inherently unsafe in the general case to access an array through a
494 // pointer whose dynamic type does not match its static type (eg., if
495 // T and the derived types had different sizes access would be
496 // incorrectly calculated). Deletion is also always undefined
497 // (C++98 [expr.delete]p3). If you're doing this, fix your code.
498 // - it cannot be const-qualified differently from T per unique_ptr spec
499 // (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting
500 // to work around this may use const_cast<const T*>().
501 explicit scoped_ptr(element_type* array) : impl_(array) {}
502
503 // Constructor. Allows construction from a nullptr.
504 scoped_ptr(std::nullptr_t) : impl_(nullptr) {}
505
506 // Constructor. Allows construction from a scoped_ptr rvalue.
507 scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {}
508
509 // operator=. Allows assignment from a scoped_ptr rvalue.
510 scoped_ptr& operator=(scoped_ptr&& rhs) {
511 impl_.TakeState(&rhs.impl_);
512 return *this;
513 }
514
515 // operator=. Allows assignment from a nullptr. Deletes the currently owned
516 // array, if any.
517 scoped_ptr& operator=(std::nullptr_t) {
518 reset();
519 return *this;
520 }
521
522 // Reset. Deletes the currently owned array, if any.
523 // Then takes ownership of a new object, if given.
524 void reset(element_type* array = nullptr) { impl_.reset(array); }
525
526 // Accessors to get the owned array.
527 element_type& operator[](size_t i) const {
528 DCHECK(impl_.get() != nullptr);
529 return impl_.get()[i];
530 }
531 element_type* get() const { return impl_.get(); }
532
533 // Access to the deleter.
534 deleter_type& get_deleter() { return impl_.get_deleter(); }
535 const deleter_type& get_deleter() const { return impl_.get_deleter(); }
536
537 // Allow scoped_ptr<element_type> to be used in boolean expressions, but not
538 // implicitly convertible to a real bool (which is dangerous).
539 private:
540 typedef base::internal::scoped_ptr_impl<element_type, deleter_type>
541 scoped_ptr::*Testable;
542
543 public:
544 operator Testable() const {
545 return impl_.get() ? &scoped_ptr::impl_ : nullptr;
546 }
547
548 // Swap two scoped pointers.
549 void swap(scoped_ptr& p2) {
550 impl_.swap(p2.impl_);
551 }
552
553 // Release a pointer.
554 // The return value is the current pointer held by this object. If this object
555 // holds a nullptr, the return value is nullptr. After this operation, this
556 // object will hold a nullptr, and will not own the object any more.
557 element_type* release() WARN_UNUSED_RESULT {
558 return impl_.release();
559 }
560
561 private:
562 // Force element_type to be a complete type.
563 enum { type_must_be_complete = sizeof(element_type) };
564
565 // Actually hold the data.
566 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
567
568 // Disable initialization from any type other than element_type*, by
569 // providing a constructor that matches such an initialization, but is
570 // private and has no definition. This is disabled because it is not safe to
571 // call delete[] on an array whose static type does not match its dynamic
572 // type.
573 template <typename U> explicit scoped_ptr(U* array);
574 explicit scoped_ptr(int disallow_construction_from_null);
575
576 // Disable reset() from any type other than element_type*, for the same
577 // reasons as the constructor above.
578 template <typename U> void reset(U* array);
579 void reset(int disallow_reset_from_null);
580 };
581
582 // Free functions
583 template <class T, class D>
584 void swap(scoped_ptr<T, D>& p1, scoped_ptr<T, D>& p2) {
585 p1.swap(p2);
586 }
587
588 template <class T1, class D1, class T2, class D2>
589 bool operator==(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) {
590 return p1.get() == p2.get();
591 }
592 template <class T, class D>
593 bool operator==(const scoped_ptr<T, D>& p, std::nullptr_t) {
594 return p.get() == nullptr;
595 }
596 template <class T, class D>
597 bool operator==(std::nullptr_t, const scoped_ptr<T, D>& p) {
598 return p.get() == nullptr;
599 }
600
601 template <class T1, class D1, class T2, class D2>
602 bool operator!=(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) {
603 return !(p1 == p2);
604 }
605 template <class T, class D>
606 bool operator!=(const scoped_ptr<T, D>& p, std::nullptr_t) {
607 return !(p == nullptr);
608 }
609 template <class T, class D>
610 bool operator!=(std::nullptr_t, const scoped_ptr<T, D>& p) {
611 return !(p == nullptr);
612 }
613
614 template <class T1, class D1, class T2, class D2>
615 bool operator<(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) {
616 return p1.get() < p2.get();
617 }
618 template <class T, class D>
619 bool operator<(const scoped_ptr<T, D>& p, std::nullptr_t) {
620 return p.get() < nullptr;
621 }
622 template <class T, class D>
623 bool operator<(std::nullptr_t, const scoped_ptr<T, D>& p) {
624 return nullptr < p.get();
625 }
626
627 template <class T1, class D1, class T2, class D2>
628 bool operator>(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) {
629 return p2 < p1;
630 }
631 template <class T, class D>
632 bool operator>(const scoped_ptr<T, D>& p, std::nullptr_t) {
633 return nullptr < p;
634 }
635 template <class T, class D>
636 bool operator>(std::nullptr_t, const scoped_ptr<T, D>& p) {
637 return p < nullptr;
638 }
639
640 template <class T1, class D1, class T2, class D2>
641 bool operator<=(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) {
642 return !(p1 > p2);
643 }
644 template <class T, class D>
645 bool operator<=(const scoped_ptr<T, D>& p, std::nullptr_t) {
646 return !(p > nullptr);
647 }
648 template <class T, class D>
649 bool operator<=(std::nullptr_t, const scoped_ptr<T, D>& p) {
650 return !(nullptr > p);
651 }
652
653 template <class T1, class D1, class T2, class D2>
654 bool operator>=(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) {
655 return !(p1 < p2);
656 }
657 template <class T, class D>
658 bool operator>=(const scoped_ptr<T, D>& p, std::nullptr_t) {
659 return !(p < nullptr);
660 }
661 template <class T, class D>
662 bool operator>=(std::nullptr_t, const scoped_ptr<T, D>& p) {
663 return !(nullptr < p);
664 }
665
666 template <typename T>
667 std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) {
668 return out << p.get();
669 }
670 #endif // defined(OS_LINUX)
671 166
672 // A function to convert T* into scoped_ptr<T> 167 // A function to convert T* into scoped_ptr<T>
673 // Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation 168 // Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation
674 // for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg)) 169 // for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
675 template <typename T> 170 template <typename T>
676 scoped_ptr<T> make_scoped_ptr(T* ptr) { 171 scoped_ptr<T> make_scoped_ptr(T* ptr) {
677 return scoped_ptr<T>(ptr); 172 return scoped_ptr<T>(ptr);
678 } 173 }
679 174
680 #endif // BASE_MEMORY_SCOPED_PTR_H_ 175 #endif // BASE_MEMORY_SCOPED_PTR_H_
OLDNEW
« no previous file with comments | « base/base.gyp ('k') | base/memory/scoped_ptr_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698