| 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 |