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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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_ |
OLD | NEW |