Planeshift

scoped_ptr.h

Go to the documentation of this file.
00001 //  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
00002 //  Copyright (c) 2001, 2002 Peter Dimov
00003 //
00004 //  Permission to copy, use, modify, sell and distribute this software
00005 //  is granted provided this copyright notice appears in all copies.
00006 //  This software is provided "as is" without express or implied
00007 //  warranty, and with no claim as to its suitability for any purpose.
00008 //
00009 //  See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation.
00010 //
00011 
00012 //  scoped_ptr mimics a built-in pointer except that it guarantees deletion
00013 //  of the object pointed to, either on destruction of the scoped_ptr or via
00014 //  an explicit reset(). scoped_ptr is a simple solution for simple needs;
00015 //  use shared_ptr or std::auto_ptr if your needs are more complex.
00016 
00017 //  *** NOTE ***
00018 //  If your scoped_ptr is a class member of class FOO pointing to a 
00019 //  forward declared type BAR (as shown below), then you MUST use a non-inlined 
00020 //  version of the destructor.  The destructor of a scoped_ptr (called from
00021 //  FOO's destructor) must have a complete definition of BAR in order to 
00022 //  destroy it.  Example:
00023 //
00024 //  -- foo.h --
00025 //  class BAR;
00026 //
00027 //  class FOO {
00028 //   public:
00029 //    FOO();
00030 //    ~FOO();  // Required for sources that instantiate class FOO to compile!
00031 //    
00032 //   private:
00033 //    scoped_ptr<BAR> bar_;
00034 //  };
00035 //
00036 //  -- foo.cc --
00037 //  #include "foo.h"
00038 //  FOO::~FOO() {} // Empty, but must be non-inlined to FOO's class definition.
00039 
00040 //  scoped_ptr_malloc added by Google
00041 //  When one of these goes out of scope, instead of doing a delete or
00042 //  delete[], it calls free().  scoped_ptr_malloc<char> is likely to see
00043 //  much more use than any other specializations.
00044 
00045 //  release() added by Google
00046 //  Use this to conditionally transfer ownership of a heap-allocated object
00047 //  to the caller, usually on method success.
00048 
00049 #ifndef COMMON_SCOPED_PTR_H_
00050 #define COMMON_SCOPED_PTR_H_
00051 
00052 #include <cstddef>            // for std::ptrdiff_t
00053 #include <assert.h>           // for assert
00054 #include <stdlib.h>           // for free() decl
00055 
00056 namespace google_breakpad {
00057 
00058 template <typename T>
00059 class scoped_ptr {
00060  private:
00061 
00062   T* ptr;
00063 
00064   scoped_ptr(scoped_ptr const &);
00065   scoped_ptr & operator=(scoped_ptr const &);
00066 
00067  public:
00068 
00069   typedef T element_type;
00070 
00071   explicit scoped_ptr(T* p = 0): ptr(p) {}
00072 
00073   ~scoped_ptr() {
00074     typedef char type_must_be_complete[sizeof(T)];
00075     delete ptr;
00076   }
00077 
00078   void reset(T* p = 0) {
00079     typedef char type_must_be_complete[sizeof(T)];
00080 
00081     if (ptr != p) {
00082       delete ptr;
00083       ptr = p;
00084     }
00085   }
00086 
00087   T& operator*() const {
00088     assert(ptr != 0);
00089     return *ptr;
00090   }
00091 
00092   T* operator->() const  {
00093     assert(ptr != 0);
00094     return ptr;
00095   }
00096 
00097   bool operator==(T* p) const {
00098     return ptr == p;
00099   }
00100 
00101   bool operator!=(T* p) const {
00102     return ptr != p;
00103   }
00104 
00105   T* get() const  {
00106     return ptr;
00107   }
00108 
00109   void swap(scoped_ptr & b) {
00110     T* tmp = b.ptr;
00111     b.ptr = ptr;
00112     ptr = tmp;
00113   }
00114 
00115   T* release() {
00116     T* tmp = ptr;
00117     ptr = 0;
00118     return tmp;
00119   }
00120 
00121  private:
00122 
00123   // no reason to use these: each scoped_ptr should have its own object
00124   template <typename U> bool operator==(scoped_ptr<U> const& p) const;
00125   template <typename U> bool operator!=(scoped_ptr<U> const& p) const;
00126 };
00127 
00128 template<typename T> inline
00129 void swap(scoped_ptr<T>& a, scoped_ptr<T>& b) {
00130   a.swap(b);
00131 }
00132 
00133 template<typename T> inline
00134 bool operator==(T* p, const scoped_ptr<T>& b) {
00135   return p == b.get();
00136 }
00137 
00138 template<typename T> inline
00139 bool operator!=(T* p, const scoped_ptr<T>& b) {
00140   return p != b.get();
00141 }
00142 
00143 //  scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
00144 //  is guaranteed, either on destruction of the scoped_array or via an explicit
00145 //  reset(). Use shared_array or std::vector if your needs are more complex.
00146 
00147 template<typename T>
00148 class scoped_array {
00149  private:
00150 
00151   T* ptr;
00152 
00153   scoped_array(scoped_array const &);
00154   scoped_array & operator=(scoped_array const &);
00155 
00156  public:
00157 
00158   typedef T element_type;
00159 
00160   explicit scoped_array(T* p = 0) : ptr(p) {}
00161 
00162   ~scoped_array() {
00163     typedef char type_must_be_complete[sizeof(T)];
00164     delete[] ptr;
00165   }
00166 
00167   void reset(T* p = 0) {
00168     typedef char type_must_be_complete[sizeof(T)];
00169 
00170     if (ptr != p) {
00171       delete [] ptr;
00172       ptr = p;
00173     }
00174   }
00175 
00176   T& operator[](std::ptrdiff_t i) const {
00177     assert(ptr != 0);
00178     assert(i >= 0);
00179     return ptr[i];
00180   }
00181 
00182   bool operator==(T* p) const {
00183     return ptr == p;
00184   }
00185 
00186   bool operator!=(T* p) const {
00187     return ptr != p;
00188   }
00189 
00190   T* get() const {
00191     return ptr;
00192   }
00193 
00194   void swap(scoped_array & b) {
00195     T* tmp = b.ptr;
00196     b.ptr = ptr;
00197     ptr = tmp;
00198   }
00199 
00200   T* release() {
00201     T* tmp = ptr;
00202     ptr = 0;
00203     return tmp;
00204   }
00205 
00206  private:
00207 
00208   // no reason to use these: each scoped_array should have its own object
00209   template <typename U> bool operator==(scoped_array<U> const& p) const;
00210   template <typename U> bool operator!=(scoped_array<U> const& p) const;
00211 };
00212 
00213 template<class T> inline
00214 void swap(scoped_array<T>& a, scoped_array<T>& b) {
00215   a.swap(b);
00216 }
00217 
00218 template<typename T> inline
00219 bool operator==(T* p, const scoped_array<T>& b) {
00220   return p == b.get();
00221 }
00222 
00223 template<typename T> inline
00224 bool operator!=(T* p, const scoped_array<T>& b) {
00225   return p != b.get();
00226 }
00227 
00228 
00229 // This class wraps the c library function free() in a class that can be
00230 // passed as a template argument to scoped_ptr_malloc below.
00231 class ScopedPtrMallocFree {
00232  public:
00233   inline void operator()(void* x) const {
00234     free(x);
00235   }
00236 };
00237 
00238 // scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a
00239 // second template argument, the functor used to free the object.
00240 
00241 template<typename T, typename FreeProc = ScopedPtrMallocFree>
00242 class scoped_ptr_malloc {
00243  private:
00244 
00245   T* ptr;
00246 
00247   scoped_ptr_malloc(scoped_ptr_malloc const &);
00248   scoped_ptr_malloc & operator=(scoped_ptr_malloc const &);
00249 
00250  public:
00251 
00252   typedef T element_type;
00253 
00254   explicit scoped_ptr_malloc(T* p = 0): ptr(p) {}
00255 
00256   ~scoped_ptr_malloc() {
00257     typedef char type_must_be_complete[sizeof(T)];
00258     free_((void*) ptr);
00259   }
00260 
00261   void reset(T* p = 0) {
00262     typedef char type_must_be_complete[sizeof(T)];
00263 
00264     if (ptr != p) {
00265       free_((void*) ptr);
00266       ptr = p;
00267     }
00268   }
00269 
00270   T& operator*() const {
00271     assert(ptr != 0);
00272     return *ptr;
00273   }
00274 
00275   T* operator->() const {
00276     assert(ptr != 0);
00277     return ptr;
00278   }
00279 
00280   bool operator==(T* p) const {
00281     return ptr == p;
00282   }
00283 
00284   bool operator!=(T* p) const {
00285     return ptr != p;
00286   }
00287 
00288   T* get() const {
00289     return ptr;
00290   }
00291 
00292   void swap(scoped_ptr_malloc & b) {
00293     T* tmp = b.ptr;
00294     b.ptr = ptr;
00295     ptr = tmp;
00296   }
00297 
00298   T* release() {
00299     T* tmp = ptr;
00300     ptr = 0;
00301     return tmp;
00302   }
00303 
00304  private:
00305 
00306   // no reason to use these: each scoped_ptr_malloc should have its own object
00307   template <typename U, typename GP>
00308   bool operator==(scoped_ptr_malloc<U, GP> const& p) const;
00309   template <typename U, typename GP>
00310   bool operator!=(scoped_ptr_malloc<U, GP> const& p) const;
00311 
00312   static FreeProc const free_;
00313 };
00314 
00315 template<typename T, typename FP>
00316 FP const scoped_ptr_malloc<T,FP>::free_ = FP();
00317 
00318 template<typename T, typename FP> inline
00319 void swap(scoped_ptr_malloc<T,FP>& a, scoped_ptr_malloc<T,FP>& b) {
00320   a.swap(b);
00321 }
00322 
00323 template<typename T, typename FP> inline
00324 bool operator==(T* p, const scoped_ptr_malloc<T,FP>& b) {
00325   return p == b.get();
00326 }
00327 
00328 template<typename T, typename FP> inline
00329 bool operator!=(T* p, const scoped_ptr_malloc<T,FP>& b) {
00330   return p != b.get();
00331 }
00332 
00333 }  // namespace google_breakpad
00334 
00335 #endif  // COMMON_SCOPED_PTR_H_