#ifndef SCOPED_PTR_H #define SCOPED_PTR_H // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. // Copyright (c) 2001, 2002 Peter Dimov // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // // See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation. // // scoped_ptr mimics a built-in pointer except that it guarantees deletion // of the object pointed to, either on destruction of the scoped_ptr or via // an explicit reset(). scoped_ptr is a simple solution for simple needs; // use shared_ptr or std::auto_ptr if your needs are more complex. // scoped_ptr_malloc added in by Google. When one of // these goes out of scope, instead of doing a delete or delete[], it // calls free(). scoped_ptr_malloc is likely to see much more // use than any other specializations. // release() added in by Google. Use this to conditionally // transfer ownership of a heap-allocated object to the caller, usually on // method success. #include // for std::ptrdiff_t #include // for assert #include // for free() decl #ifdef _WIN32 namespace std { using ::ptrdiff_t; }; #endif // _WIN32 namespace buzz { template class scoped_ptr { private: T* ptr; scoped_ptr(scoped_ptr const &); scoped_ptr & operator=(scoped_ptr const &); public: typedef T element_type; explicit scoped_ptr(T* p = 0): ptr(p) {} ~scoped_ptr() { typedef char type_must_be_complete[sizeof(T)]; delete ptr; } void reset(T* p = 0) { typedef char type_must_be_complete[sizeof(T)]; if (ptr != p) { delete ptr; ptr = p; } } T& operator*() const { assert(ptr != 0); return *ptr; } T* operator->() const { assert(ptr != 0); return ptr; } T* get() const { return ptr; } void swap(scoped_ptr & b) { T* tmp = b.ptr; b.ptr = ptr; ptr = tmp; } T* release() { T* tmp = ptr; ptr = 0; return tmp; } T** accept() { if (ptr) { delete ptr; ptr = 0; } return &ptr; } T** use() { return &ptr; } }; template inline void swap(scoped_ptr& a, scoped_ptr& b) { a.swap(b); } // scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to // is guaranteed, either on destruction of the scoped_array or via an explicit // reset(). Use shared_array or std::vector if your needs are more complex. template class scoped_array { private: T* ptr; scoped_array(scoped_array const &); scoped_array & operator=(scoped_array const &); public: typedef T element_type; explicit scoped_array(T* p = 0) : ptr(p) {} ~scoped_array() { typedef char type_must_be_complete[sizeof(T)]; delete[] ptr; } void reset(T* p = 0) { typedef char type_must_be_complete[sizeof(T)]; if (ptr != p) { delete [] ptr; ptr = p; } } T& operator[](std::ptrdiff_t i) const { assert(ptr != 0); assert(i >= 0); return ptr[i]; } T* get() const { return ptr; } void swap(scoped_array & b) { T* tmp = b.ptr; b.ptr = ptr; ptr = tmp; } T* release() { T* tmp = ptr; ptr = 0; return tmp; } T** accept() { if (ptr) { delete [] ptr; ptr = 0; } return &ptr; } }; template inline void swap(scoped_array& a, scoped_array& b) { a.swap(b); } // scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a // second template argument, the function used to free the object. template class scoped_ptr_malloc { private: T* ptr; scoped_ptr_malloc(scoped_ptr_malloc const &); scoped_ptr_malloc & operator=(scoped_ptr_malloc const &); public: typedef T element_type; explicit scoped_ptr_malloc(T* p = 0): ptr(p) {} ~scoped_ptr_malloc() { typedef char type_must_be_complete[sizeof(T)]; FF(static_cast(ptr)); } void reset(T* p = 0) { typedef char type_must_be_complete[sizeof(T)]; if (ptr != p) { FF(static_cast(ptr)); ptr = p; } } T& operator*() const { assert(ptr != 0); return *ptr; } T* operator->() const { assert(ptr != 0); return ptr; } T* get() const { return ptr; } void swap(scoped_ptr_malloc & b) { T* tmp = b.ptr; b.ptr = ptr; ptr = tmp; } T* release() { T* tmp = ptr; ptr = 0; return tmp; } T** accept() { if (ptr) { FF(static_cast(ptr)); ptr = 0; } return &ptr; } }; template inline void swap(scoped_ptr_malloc& a, scoped_ptr_malloc& b) { a.swap(b); } } using buzz::scoped_ptr; #endif // #ifndef SCOPED_PTR_H