michael@0: // Copyright (c) 2012 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: // Scopers help you manage ownership of a pointer, helping you easily manage the michael@0: // a pointer within a scope, and automatically destroying the pointer at the michael@0: // end of a scope. There are two main classes you will use, which correspond michael@0: // to the operators new/delete and new[]/delete[]. michael@0: // michael@0: // Example usage (scoped_ptr): michael@0: // { michael@0: // scoped_ptr foo(new Foo("wee")); michael@0: // } // foo goes out of scope, releasing the pointer with it. michael@0: // michael@0: // { michael@0: // scoped_ptr foo; // No pointer managed. michael@0: // foo.reset(new Foo("wee")); // Now a pointer is managed. michael@0: // foo.reset(new Foo("wee2")); // Foo("wee") was destroyed. michael@0: // foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed. michael@0: // foo->Method(); // Foo::Method() called. michael@0: // foo.get()->Method(); // Foo::Method() called. michael@0: // SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer michael@0: // // manages a pointer. michael@0: // foo.reset(new Foo("wee4")); // foo manages a pointer again. michael@0: // foo.reset(); // Foo("wee4") destroyed, foo no longer michael@0: // // manages a pointer. michael@0: // } // foo wasn't managing a pointer, so nothing was destroyed. michael@0: // michael@0: // Example usage (scoped_ptr): michael@0: // { michael@0: // scoped_ptr foo(new Foo[100]); michael@0: // foo.get()->Method(); // Foo::Method on the 0th element. michael@0: // foo[10].Method(); // Foo::Method on the 10th element. michael@0: // } michael@0: // michael@0: // These scopers also implement part of the functionality of C++11 unique_ptr michael@0: // in that they are "movable but not copyable." You can use the scopers in michael@0: // the parameter and return types of functions to signify ownership transfer michael@0: // in to and out of a function. When calling a function that has a scoper michael@0: // as the argument type, it must be called with the result of an analogous michael@0: // scoper's Pass() function or another function that generates a temporary; michael@0: // passing by copy will NOT work. Here is an example using scoped_ptr: michael@0: // michael@0: // void TakesOwnership(scoped_ptr arg) { michael@0: // // Do something with arg michael@0: // } michael@0: // scoped_ptr CreateFoo() { michael@0: // // No need for calling Pass() because we are constructing a temporary michael@0: // // for the return value. michael@0: // return scoped_ptr(new Foo("new")); michael@0: // } michael@0: // scoped_ptr PassThru(scoped_ptr arg) { michael@0: // return arg.Pass(); michael@0: // } michael@0: // michael@0: // { michael@0: // scoped_ptr ptr(new Foo("yay")); // ptr manages Foo("yay"). michael@0: // TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay"). michael@0: // scoped_ptr ptr2 = CreateFoo(); // ptr2 owns the return Foo. michael@0: // scoped_ptr ptr3 = // ptr3 now owns what was in ptr2. michael@0: // PassThru(ptr2.Pass()); // ptr2 is correspondingly NULL. michael@0: // } michael@0: // michael@0: // Notice that if you do not call Pass() when returning from PassThru(), or michael@0: // when invoking TakesOwnership(), the code will not compile because scopers michael@0: // are not copyable; they only implement move semantics which require calling michael@0: // the Pass() function to signify a destructive transfer of state. CreateFoo() michael@0: // is different though because we are constructing a temporary on the return michael@0: // line and thus can avoid needing to call Pass(). michael@0: // michael@0: // Pass() properly handles upcast in assignment, i.e. you can assign michael@0: // scoped_ptr to scoped_ptr: michael@0: // michael@0: // scoped_ptr foo(new Foo()); michael@0: // scoped_ptr parent = foo.Pass(); michael@0: // michael@0: // PassAs<>() should be used to upcast return value in return statement: michael@0: // michael@0: // scoped_ptr CreateFoo() { michael@0: // scoped_ptr result(new FooChild()); michael@0: // return result.PassAs(); michael@0: // } michael@0: // michael@0: // Note that PassAs<>() is implemented only for scoped_ptr, but not for michael@0: // scoped_ptr. This is because casting array pointers may not be safe. michael@0: michael@0: #ifndef BASE_MEMORY_SCOPED_PTR_H_ michael@0: #define BASE_MEMORY_SCOPED_PTR_H_ michael@0: michael@0: // This is an implementation designed to match the anticipated future TR2 michael@0: // implementation of the scoped_ptr class and scoped_ptr_malloc (deprecated). michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #include // For std::swap(). michael@0: michael@0: #include "base/basictypes.h" michael@0: #include "base/compiler_specific.h" michael@0: #include "base/move.h" michael@0: #include "base/template_util.h" michael@0: michael@0: namespace base { michael@0: michael@0: namespace subtle { michael@0: class RefCountedBase; michael@0: class RefCountedThreadSafeBase; michael@0: } // namespace subtle michael@0: michael@0: // Function object which deletes its parameter, which must be a pointer. michael@0: // If C is an array type, invokes 'delete[]' on the parameter; otherwise, michael@0: // invokes 'delete'. The default deleter for scoped_ptr. michael@0: template michael@0: struct DefaultDeleter { michael@0: DefaultDeleter() {} michael@0: template DefaultDeleter(const DefaultDeleter& other) { michael@0: // IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor michael@0: // if U* is implicitly convertible to T* and U is not an array type. michael@0: // michael@0: // Correct implementation should use SFINAE to disable this michael@0: // constructor. However, since there are no other 1-argument constructors, michael@0: // using a COMPILE_ASSERT() based on is_convertible<> and requiring michael@0: // complete types is simpler and will cause compile failures for equivalent michael@0: // misuses. michael@0: // michael@0: // Note, the is_convertible check also ensures that U is not an michael@0: // array. T is guaranteed to be a non-array, so any U* where U is an array michael@0: // cannot convert to T*. michael@0: enum { T_must_be_complete = sizeof(T) }; michael@0: enum { U_must_be_complete = sizeof(U) }; michael@0: COMPILE_ASSERT((base::is_convertible::value), michael@0: U_ptr_must_implicitly_convert_to_T_ptr); michael@0: } michael@0: inline void operator()(T* ptr) const { michael@0: enum { type_must_be_complete = sizeof(T) }; michael@0: delete ptr; michael@0: } michael@0: }; michael@0: michael@0: // Specialization of DefaultDeleter for array types. michael@0: template michael@0: struct DefaultDeleter { michael@0: inline void operator()(T* ptr) const { michael@0: enum { type_must_be_complete = sizeof(T) }; michael@0: delete[] ptr; michael@0: } michael@0: michael@0: private: michael@0: // Disable this operator for any U != T because it is undefined to execute michael@0: // an array delete when the static type of the array mismatches the dynamic michael@0: // type. michael@0: // michael@0: // References: michael@0: // C++98 [expr.delete]p3 michael@0: // http://cplusplus.github.com/LWG/lwg-defects.html#938 michael@0: template void operator()(U* array) const; michael@0: }; michael@0: michael@0: template michael@0: struct DefaultDeleter { michael@0: // Never allow someone to declare something like scoped_ptr. michael@0: COMPILE_ASSERT(sizeof(T) == -1, do_not_use_array_with_size_as_type); michael@0: }; michael@0: michael@0: // Function object which invokes 'free' on its parameter, which must be michael@0: // a pointer. Can be used to store malloc-allocated pointers in scoped_ptr: michael@0: // michael@0: // scoped_ptr foo_ptr( michael@0: // static_cast(malloc(sizeof(int)))); michael@0: struct FreeDeleter { michael@0: inline void operator()(void* ptr) const { michael@0: free(ptr); michael@0: } michael@0: }; michael@0: michael@0: namespace internal { michael@0: michael@0: template struct IsNotRefCounted { michael@0: enum { michael@0: value = !base::is_convertible::value && michael@0: !base::is_convertible:: michael@0: value michael@0: }; michael@0: }; michael@0: michael@0: // Minimal implementation of the core logic of scoped_ptr, suitable for michael@0: // reuse in both scoped_ptr and its specializations. michael@0: template michael@0: class scoped_ptr_impl { michael@0: public: michael@0: explicit scoped_ptr_impl(T* p) : data_(p) { } michael@0: michael@0: // Initializer for deleters that have data parameters. michael@0: scoped_ptr_impl(T* p, const D& d) : data_(p, d) {} michael@0: michael@0: // Templated constructor that destructively takes the value from another michael@0: // scoped_ptr_impl. michael@0: template michael@0: scoped_ptr_impl(scoped_ptr_impl* other) michael@0: : data_(other->release(), other->get_deleter()) { michael@0: // We do not support move-only deleters. We could modify our move michael@0: // emulation to have base::subtle::move() and base::subtle::forward() michael@0: // functions that are imperfect emulations of their C++11 equivalents, michael@0: // but until there's a requirement, just assume deleters are copyable. michael@0: } michael@0: michael@0: template michael@0: void TakeState(scoped_ptr_impl* other) { michael@0: // See comment in templated constructor above regarding lack of support michael@0: // for move-only deleters. michael@0: reset(other->release()); michael@0: get_deleter() = other->get_deleter(); michael@0: } michael@0: michael@0: ~scoped_ptr_impl() { michael@0: if (data_.ptr != NULL) { michael@0: // Not using get_deleter() saves one function call in non-optimized michael@0: // builds. michael@0: static_cast(data_)(data_.ptr); michael@0: } michael@0: } michael@0: michael@0: void reset(T* p) { michael@0: // This is a self-reset, which is no longer allowed: http://crbug.com/162971 michael@0: if (p != NULL && p == data_.ptr) michael@0: abort(); michael@0: michael@0: // Note that running data_.ptr = p can lead to undefined behavior if michael@0: // get_deleter()(get()) deletes this. In order to pevent this, reset() michael@0: // should update the stored pointer before deleting its old value. michael@0: // michael@0: // However, changing reset() to use that behavior may cause current code to michael@0: // break in unexpected ways. If the destruction of the owned object michael@0: // dereferences the scoped_ptr when it is destroyed by a call to reset(), michael@0: // then it will incorrectly dispatch calls to |p| rather than the original michael@0: // value of |data_.ptr|. michael@0: // michael@0: // During the transition period, set the stored pointer to NULL while michael@0: // deleting the object. Eventually, this safety check will be removed to michael@0: // prevent the scenario initially described from occuring and michael@0: // http://crbug.com/176091 can be closed. michael@0: T* old = data_.ptr; michael@0: data_.ptr = NULL; michael@0: if (old != NULL) michael@0: static_cast(data_)(old); michael@0: data_.ptr = p; michael@0: } michael@0: michael@0: T* get() const { return data_.ptr; } michael@0: michael@0: D& get_deleter() { return data_; } michael@0: const D& get_deleter() const { return data_; } michael@0: michael@0: void swap(scoped_ptr_impl& p2) { michael@0: // Standard swap idiom: 'using std::swap' ensures that std::swap is michael@0: // present in the overload set, but we call swap unqualified so that michael@0: // any more-specific overloads can be used, if available. michael@0: using std::swap; michael@0: swap(static_cast(data_), static_cast(p2.data_)); michael@0: swap(data_.ptr, p2.data_.ptr); michael@0: } michael@0: michael@0: T* release() { michael@0: T* old_ptr = data_.ptr; michael@0: data_.ptr = NULL; michael@0: return old_ptr; michael@0: } michael@0: michael@0: private: michael@0: // Needed to allow type-converting constructor. michael@0: template friend class scoped_ptr_impl; michael@0: michael@0: // Use the empty base class optimization to allow us to have a D michael@0: // member, while avoiding any space overhead for it when D is an michael@0: // empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good michael@0: // discussion of this technique. michael@0: struct Data : public D { michael@0: explicit Data(T* ptr_in) : ptr(ptr_in) {} michael@0: Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {} michael@0: T* ptr; michael@0: }; michael@0: michael@0: Data data_; michael@0: michael@0: DISALLOW_COPY_AND_ASSIGN(scoped_ptr_impl); michael@0: }; michael@0: michael@0: } // namespace internal michael@0: michael@0: } // namespace base michael@0: michael@0: // A scoped_ptr is like a T*, except that the destructor of scoped_ptr michael@0: // automatically deletes the pointer it holds (if any). michael@0: // That is, scoped_ptr owns the T object that it points to. michael@0: // Like a T*, a scoped_ptr may hold either NULL or a pointer to a T object. michael@0: // Also like T*, scoped_ptr is thread-compatible, and once you michael@0: // dereference it, you get the thread safety guarantees of T. michael@0: // michael@0: // The size of scoped_ptr is small. On most compilers, when using the michael@0: // DefaultDeleter, sizeof(scoped_ptr) == sizeof(T*). Custom deleters will michael@0: // increase the size proportional to whatever state they need to have. See michael@0: // comments inside scoped_ptr_impl<> for details. michael@0: // michael@0: // Current implementation targets having a strict subset of C++11's michael@0: // unique_ptr<> features. Known deficiencies include not supporting move-only michael@0: // deleteres, function pointers as deleters, and deleters with reference michael@0: // types. michael@0: template > michael@0: class scoped_ptr { michael@0: MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue) michael@0: michael@0: COMPILE_ASSERT(base::internal::IsNotRefCounted::value, michael@0: T_is_refcounted_type_and_needs_scoped_refptr); michael@0: michael@0: public: michael@0: // The element and deleter types. michael@0: typedef T element_type; michael@0: typedef D deleter_type; michael@0: michael@0: // Constructor. Defaults to initializing with NULL. michael@0: scoped_ptr() : impl_(NULL) { } michael@0: michael@0: // Constructor. Takes ownership of p. michael@0: explicit scoped_ptr(element_type* p) : impl_(p) { } michael@0: michael@0: // Constructor. Allows initialization of a stateful deleter. michael@0: scoped_ptr(element_type* p, const D& d) : impl_(p, d) { } michael@0: michael@0: // Constructor. Allows construction from a scoped_ptr rvalue for a michael@0: // convertible type and deleter. michael@0: // michael@0: // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct michael@0: // from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor michael@0: // has different post-conditions if D is a reference type. Since this michael@0: // implementation does not support deleters with reference type, michael@0: // we do not need a separate move constructor allowing us to avoid one michael@0: // use of SFINAE. You only need to care about this if you modify the michael@0: // implementation of scoped_ptr. michael@0: template michael@0: scoped_ptr(scoped_ptr other) : impl_(&other.impl_) { michael@0: COMPILE_ASSERT(!base::is_array::value, U_cannot_be_an_array); michael@0: } michael@0: michael@0: // Constructor. Move constructor for C++03 move emulation of this type. michael@0: scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { } michael@0: michael@0: // operator=. Allows assignment from a scoped_ptr rvalue for a convertible michael@0: // type and deleter. michael@0: // michael@0: // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from michael@0: // the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated michael@0: // form has different requirements on for move-only Deleters. Since this michael@0: // implementation does not support move-only Deleters, we do not need a michael@0: // separate move assignment operator allowing us to avoid one use of SFINAE. michael@0: // You only need to care about this if you modify the implementation of michael@0: // scoped_ptr. michael@0: template michael@0: scoped_ptr& operator=(scoped_ptr rhs) { michael@0: COMPILE_ASSERT(!base::is_array::value, U_cannot_be_an_array); michael@0: impl_.TakeState(&rhs.impl_); michael@0: return *this; michael@0: } michael@0: michael@0: // Reset. Deletes the currently owned object, if any. michael@0: // Then takes ownership of a new object, if given. michael@0: void reset(element_type* p = NULL) { impl_.reset(p); } michael@0: michael@0: // Accessors to get the owned object. michael@0: // operator* and operator-> will assert() if there is no current object. michael@0: element_type& operator*() const { michael@0: assert(impl_.get() != NULL); michael@0: return *impl_.get(); michael@0: } michael@0: element_type* operator->() const { michael@0: assert(impl_.get() != NULL); michael@0: return impl_.get(); michael@0: } michael@0: element_type* get() const { return impl_.get(); } michael@0: michael@0: // Access to the deleter. michael@0: deleter_type& get_deleter() { return impl_.get_deleter(); } michael@0: const deleter_type& get_deleter() const { return impl_.get_deleter(); } michael@0: michael@0: // Allow scoped_ptr to be used in boolean expressions, but not michael@0: // implicitly convertible to a real bool (which is dangerous). michael@0: // michael@0: // Note that this trick is only safe when the == and != operators michael@0: // are declared explicitly, as otherwise "scoped_ptr1 == michael@0: // scoped_ptr2" will compile but do the wrong thing (i.e., convert michael@0: // to Testable and then do the comparison). michael@0: private: michael@0: typedef base::internal::scoped_ptr_impl michael@0: scoped_ptr::*Testable; michael@0: michael@0: public: michael@0: operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; } michael@0: michael@0: // Comparison operators. michael@0: // These return whether two scoped_ptr refer to the same object, not just to michael@0: // two different but equal objects. michael@0: bool operator==(const element_type* p) const { return impl_.get() == p; } michael@0: bool operator!=(const element_type* p) const { return impl_.get() != p; } michael@0: michael@0: // Swap two scoped pointers. michael@0: void swap(scoped_ptr& p2) { michael@0: impl_.swap(p2.impl_); michael@0: } michael@0: michael@0: // Release a pointer. michael@0: // The return value is the current pointer held by this object. michael@0: // If this object holds a NULL pointer, the return value is NULL. michael@0: // After this operation, this object will hold a NULL pointer, michael@0: // and will not own the object any more. michael@0: element_type* release() WARN_UNUSED_RESULT { michael@0: return impl_.release(); michael@0: } michael@0: michael@0: // C++98 doesn't support functions templates with default parameters which michael@0: // makes it hard to write a PassAs() that understands converting the deleter michael@0: // while preserving simple calling semantics. michael@0: // michael@0: // Until there is a use case for PassAs() with custom deleters, just ignore michael@0: // the custom deleter. michael@0: template michael@0: scoped_ptr PassAs() { michael@0: return scoped_ptr(Pass()); michael@0: } michael@0: michael@0: private: michael@0: // Needed to reach into |impl_| in the constructor. michael@0: template friend class scoped_ptr; michael@0: base::internal::scoped_ptr_impl impl_; michael@0: michael@0: // Forbidden for API compatibility with std::unique_ptr. michael@0: explicit scoped_ptr(int disallow_construction_from_null); michael@0: michael@0: // Forbid comparison of scoped_ptr types. If U != T, it totally michael@0: // doesn't make sense, and if U == T, it still doesn't make sense michael@0: // because you should never have the same object owned by two different michael@0: // scoped_ptrs. michael@0: template bool operator==(scoped_ptr const& p2) const; michael@0: template bool operator!=(scoped_ptr const& p2) const; michael@0: }; michael@0: michael@0: template michael@0: class scoped_ptr { michael@0: MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue) michael@0: michael@0: public: michael@0: // The element and deleter types. michael@0: typedef T element_type; michael@0: typedef D deleter_type; michael@0: michael@0: // Constructor. Defaults to initializing with NULL. michael@0: scoped_ptr() : impl_(NULL) { } michael@0: michael@0: // Constructor. Stores the given array. Note that the argument's type michael@0: // must exactly match T*. In particular: michael@0: // - it cannot be a pointer to a type derived from T, because it is michael@0: // inherently unsafe in the general case to access an array through a michael@0: // pointer whose dynamic type does not match its static type (eg., if michael@0: // T and the derived types had different sizes access would be michael@0: // incorrectly calculated). Deletion is also always undefined michael@0: // (C++98 [expr.delete]p3). If you're doing this, fix your code. michael@0: // - it cannot be NULL, because NULL is an integral expression, not a michael@0: // pointer to T. Use the no-argument version instead of explicitly michael@0: // passing NULL. michael@0: // - it cannot be const-qualified differently from T per unique_ptr spec michael@0: // (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting michael@0: // to work around this may use implicit_cast(). michael@0: // However, because of the first bullet in this comment, users MUST michael@0: // NOT use implicit_cast() to upcast the static type of the array. michael@0: explicit scoped_ptr(element_type* array) : impl_(array) { } michael@0: michael@0: // Constructor. Move constructor for C++03 move emulation of this type. michael@0: scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { } michael@0: michael@0: // operator=. Move operator= for C++03 move emulation of this type. michael@0: scoped_ptr& operator=(RValue rhs) { michael@0: impl_.TakeState(&rhs.object->impl_); michael@0: return *this; michael@0: } michael@0: michael@0: // Reset. Deletes the currently owned array, if any. michael@0: // Then takes ownership of a new object, if given. michael@0: void reset(element_type* array = NULL) { impl_.reset(array); } michael@0: michael@0: // Accessors to get the owned array. michael@0: element_type& operator[](size_t i) const { michael@0: assert(impl_.get() != NULL); michael@0: return impl_.get()[i]; michael@0: } michael@0: element_type* get() const { return impl_.get(); } michael@0: michael@0: // Access to the deleter. michael@0: deleter_type& get_deleter() { return impl_.get_deleter(); } michael@0: const deleter_type& get_deleter() const { return impl_.get_deleter(); } michael@0: michael@0: // Allow scoped_ptr to be used in boolean expressions, but not michael@0: // implicitly convertible to a real bool (which is dangerous). michael@0: private: michael@0: typedef base::internal::scoped_ptr_impl michael@0: scoped_ptr::*Testable; michael@0: michael@0: public: michael@0: operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; } michael@0: michael@0: // Comparison operators. michael@0: // These return whether two scoped_ptr refer to the same object, not just to michael@0: // two different but equal objects. michael@0: bool operator==(element_type* array) const { return impl_.get() == array; } michael@0: bool operator!=(element_type* array) const { return impl_.get() != array; } michael@0: michael@0: // Swap two scoped pointers. michael@0: void swap(scoped_ptr& p2) { michael@0: impl_.swap(p2.impl_); michael@0: } michael@0: michael@0: // Release a pointer. michael@0: // The return value is the current pointer held by this object. michael@0: // If this object holds a NULL pointer, the return value is NULL. michael@0: // After this operation, this object will hold a NULL pointer, michael@0: // and will not own the object any more. michael@0: element_type* release() WARN_UNUSED_RESULT { michael@0: return impl_.release(); michael@0: } michael@0: michael@0: private: michael@0: // Force element_type to be a complete type. michael@0: enum { type_must_be_complete = sizeof(element_type) }; michael@0: michael@0: // Actually hold the data. michael@0: base::internal::scoped_ptr_impl impl_; michael@0: michael@0: // Disable initialization from any type other than element_type*, by michael@0: // providing a constructor that matches such an initialization, but is michael@0: // private and has no definition. This is disabled because it is not safe to michael@0: // call delete[] on an array whose static type does not match its dynamic michael@0: // type. michael@0: template explicit scoped_ptr(U* array); michael@0: explicit scoped_ptr(int disallow_construction_from_null); michael@0: michael@0: // Disable reset() from any type other than element_type*, for the same michael@0: // reasons as the constructor above. michael@0: template void reset(U* array); michael@0: void reset(int disallow_reset_from_null); michael@0: michael@0: // Forbid comparison of scoped_ptr types. If U != T, it totally michael@0: // doesn't make sense, and if U == T, it still doesn't make sense michael@0: // because you should never have the same object owned by two different michael@0: // scoped_ptrs. michael@0: template bool operator==(scoped_ptr const& p2) const; michael@0: template bool operator!=(scoped_ptr const& p2) const; michael@0: }; michael@0: michael@0: // Free functions michael@0: template michael@0: void swap(scoped_ptr& p1, scoped_ptr& p2) { michael@0: p1.swap(p2); michael@0: } michael@0: michael@0: template michael@0: bool operator==(T* p1, const scoped_ptr& p2) { michael@0: return p1 == p2.get(); michael@0: } michael@0: michael@0: template michael@0: bool operator!=(T* p1, const scoped_ptr& p2) { michael@0: return p1 != p2.get(); michael@0: } michael@0: michael@0: // DEPRECATED: Use scoped_ptr instead. michael@0: // michael@0: // scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a michael@0: // second template argument, the functor used to free the object. michael@0: michael@0: template michael@0: class scoped_ptr_malloc { michael@0: MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr_malloc, RValue) michael@0: michael@0: public: michael@0: michael@0: // The element type michael@0: typedef C element_type; michael@0: michael@0: // Constructor. Defaults to initializing with NULL. michael@0: // There is no way to create an uninitialized scoped_ptr. michael@0: // The input parameter must be allocated with an allocator that matches the michael@0: // Free functor. For the default Free functor, this is malloc, calloc, or michael@0: // realloc. michael@0: explicit scoped_ptr_malloc(C* p = NULL): ptr_(p) {} michael@0: michael@0: // Constructor. Move constructor for C++03 move emulation of this type. michael@0: scoped_ptr_malloc(RValue rvalue) michael@0: : ptr_(rvalue.object->release()) { michael@0: } michael@0: michael@0: // Destructor. If there is a C object, call the Free functor. michael@0: ~scoped_ptr_malloc() { michael@0: reset(); michael@0: } michael@0: michael@0: // operator=. Move operator= for C++03 move emulation of this type. michael@0: scoped_ptr_malloc& operator=(RValue rhs) { michael@0: reset(rhs.object->release()); michael@0: return *this; michael@0: } michael@0: michael@0: // Reset. Calls the Free functor on the current owned object, if any. michael@0: // Then takes ownership of a new object, if given. michael@0: // this->reset(this->get()) works. michael@0: void reset(C* p = NULL) { michael@0: if (ptr_ != p) { michael@0: if (ptr_ != NULL) { michael@0: FreeProc free_proc; michael@0: free_proc(ptr_); michael@0: } michael@0: ptr_ = p; michael@0: } michael@0: } michael@0: michael@0: // Get the current object. michael@0: // operator* and operator-> will cause an assert() failure if there is michael@0: // no current object. michael@0: C& operator*() const { michael@0: assert(ptr_ != NULL); michael@0: return *ptr_; michael@0: } michael@0: michael@0: C* operator->() const { michael@0: assert(ptr_ != NULL); michael@0: return ptr_; michael@0: } michael@0: michael@0: C* get() const { michael@0: return ptr_; michael@0: } michael@0: michael@0: // Allow scoped_ptr_malloc to be used in boolean expressions, but not michael@0: // implicitly convertible to a real bool (which is dangerous). michael@0: typedef C* scoped_ptr_malloc::*Testable; michael@0: operator Testable() const { return ptr_ ? &scoped_ptr_malloc::ptr_ : NULL; } michael@0: michael@0: // Comparison operators. michael@0: // These return whether a scoped_ptr_malloc and a plain pointer refer michael@0: // to the same object, not just to two different but equal objects. michael@0: // For compatibility with the boost-derived implementation, these michael@0: // take non-const arguments. michael@0: bool operator==(C* p) const { michael@0: return ptr_ == p; michael@0: } michael@0: michael@0: bool operator!=(C* p) const { michael@0: return ptr_ != p; michael@0: } michael@0: michael@0: // Swap two scoped pointers. michael@0: void swap(scoped_ptr_malloc & b) { michael@0: C* tmp = b.ptr_; michael@0: b.ptr_ = ptr_; michael@0: ptr_ = tmp; michael@0: } michael@0: michael@0: // Release a pointer. michael@0: // The return value is the current pointer held by this object. michael@0: // If this object holds a NULL pointer, the return value is NULL. michael@0: // After this operation, this object will hold a NULL pointer, michael@0: // and will not own the object any more. michael@0: C* release() WARN_UNUSED_RESULT { michael@0: C* tmp = ptr_; michael@0: ptr_ = NULL; michael@0: return tmp; michael@0: } michael@0: michael@0: private: michael@0: C* ptr_; michael@0: michael@0: // no reason to use these: each scoped_ptr_malloc should have its own object michael@0: template michael@0: bool operator==(scoped_ptr_malloc const& p) const; michael@0: template michael@0: bool operator!=(scoped_ptr_malloc const& p) const; michael@0: }; michael@0: michael@0: template inline michael@0: void swap(scoped_ptr_malloc& a, scoped_ptr_malloc& b) { michael@0: a.swap(b); michael@0: } michael@0: michael@0: template inline michael@0: bool operator==(C* p, const scoped_ptr_malloc& b) { michael@0: return p == b.get(); michael@0: } michael@0: michael@0: template inline michael@0: bool operator!=(C* p, const scoped_ptr_malloc& b) { michael@0: return p != b.get(); michael@0: } michael@0: michael@0: // A function to convert T* into scoped_ptr michael@0: // Doing e.g. make_scoped_ptr(new FooBarBaz(arg)) is a shorter notation michael@0: // for scoped_ptr >(new FooBarBaz(arg)) michael@0: template michael@0: scoped_ptr make_scoped_ptr(T* ptr) { michael@0: return scoped_ptr(ptr); michael@0: } michael@0: michael@0: #endif // BASE_MEMORY_SCOPED_PTR_H_