1 #ifndef BASE_SCOPED_PTR_H 2 #define BASE_SCOPED_PTR_H 3 4 // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. 5 // Copyright (c) 2001, 2002 Peter Dimov 6 // 7 // Permission to copy, use, modify, sell and distribute this software 8 // is granted provided this copyright notice appears in all copies. 9 // This software is provided "as is" without express or implied 10 // warranty, and with no claim as to its suitability for any purpose. 11 // 12 // See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation. 13 // 14 15 // scoped_ptr mimics a built-in pointer except that it guarantees deletion 16 // of the object pointed to, either on destruction of the scoped_ptr or via 17 // an explicit reset(). scoped_ptr is a simple solution for simple needs; 18 // use shared_ptr or std::auto_ptr if your needs are more complex. 19 20 // *** NOTE *** 21 // If your scoped_ptr is a class member of class FOO pointing to a 22 // forward declared type BAR (as shown below), then you MUST use a non-inlined 23 // version of the destructor. The destructor of a scoped_ptr (called from 24 // FOO's destructor) must have a complete definition of BAR in order to 25 // destroy it. Example: 26 // 27 // -- foo.h -- 28 // class BAR; 29 // 30 // class FOO { 31 // public: 32 // FOO(); 33 // ~FOO(); // Required for sources that instantiate class FOO to compile! 34 // 35 // private: 36 // scoped_ptr<BAR> bar_; 37 // }; 38 // 39 // -- foo.cc -- 40 // #include "foo.h" 41 // FOO::~FOO() {} // Empty, but must be non-inlined to FOO's class definition. 42 43 #include <cstddef> // for std::ptrdiff_t 44 #include <assert.h> // for assert 45 #include <stdlib.h> // for free() decl 46 47 template <typename T> 48 class scoped_ptr { 49 private: 50 51 T* ptr; 52 53 scoped_ptr(scoped_ptr const &); 54 scoped_ptr & operator=(scoped_ptr const &); 55 56 public: 57 58 typedef T element_type; 59 60 explicit scoped_ptr(T* p = 0): ptr(p) {} 61 62 ~scoped_ptr() { 63 typedef char type_must_be_complete[sizeof(T)]; 64 delete ptr; 65 } 66 67 void reset(T* p = 0) { 68 typedef char type_must_be_complete[sizeof(T)]; 69 70 if (ptr != p) { 71 delete ptr; 72 ptr = p; 73 } 74 } 75 76 T& operator*() const { 77 assert(ptr != 0); 78 return *ptr; 79 } 80 81 T* operator->() const { 82 assert(ptr != 0); 83 return ptr; 84 } 85 86 bool operator==(T* p) const { 87 return ptr == p; 88 } 89 90 bool operator!=(T* p) const { 91 return ptr != p; 92 } 93 94 T* get() const { 95 return ptr; 96 } 97 98 void swap(scoped_ptr & b) { 99 T* tmp = b.ptr; 100 b.ptr = ptr; 101 ptr = tmp; 102 } 103 104 T* release() { 105 T* tmp = ptr; 106 ptr = 0; 107 return tmp; 108 } 109 110 private: 111 112 // no reason to use these: each scoped_ptr should have its own object 113 template <typename U> bool operator==(scoped_ptr<U> const& p) const; 114 template <typename U> bool operator!=(scoped_ptr<U> const& p) const; 115 }; 116 117 template<typename T> inline 118 void swap(scoped_ptr<T>& a, scoped_ptr<T>& b) { 119 a.swap(b); 120 } 121 122 template<typename T> inline 123 bool operator==(T* p, const scoped_ptr<T>& b) { 124 return p == b.get(); 125 } 126 127 template<typename T> inline 128 bool operator!=(T* p, const scoped_ptr<T>& b) { 129 return p != b.get(); 130 } 131 132 // scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to 133 // is guaranteed, either on destruction of the scoped_array or via an explicit 134 // reset(). Use shared_array or std::vector if your needs are more complex. 135 136 template<typename T> 137 class scoped_array { 138 private: 139 140 T* ptr; 141 142 scoped_array(scoped_array const &); 143 scoped_array & operator=(scoped_array const &); 144 145 public: 146 147 typedef T element_type; 148 149 explicit scoped_array(T* p = 0) : ptr(p) {} 150 151 ~scoped_array() { 152 typedef char type_must_be_complete[sizeof(T)]; 153 delete[] ptr; 154 } 155 156 void reset(T* p = 0) { 157 typedef char type_must_be_complete[sizeof(T)]; 158 159 if (ptr != p) { 160 delete [] ptr; 161 ptr = p; 162 } 163 } 164 165 T& operator[](std::ptrdiff_t i) const { 166 assert(ptr != 0); 167 assert(i >= 0); 168 return ptr[i]; 169 } 170 171 bool operator==(T* p) const { 172 return ptr == p; 173 } 174 175 bool operator!=(T* p) const { 176 return ptr != p; 177 } 178 179 T* get() const { 180 return ptr; 181 } 182 183 void swap(scoped_array & b) { 184 T* tmp = b.ptr; 185 b.ptr = ptr; 186 ptr = tmp; 187 } 188 189 T* release() { 190 T* tmp = ptr; 191 ptr = 0; 192 return tmp; 193 } 194 195 private: 196 197 // no reason to use these: each scoped_array should have its own object 198 template <typename U> bool operator==(scoped_array<U> const& p) const; 199 template <typename U> bool operator!=(scoped_array<U> const& p) const; 200 }; 201 202 template<class T> inline 203 void swap(::scoped_array<T>& a, ::scoped_array<T>& b) { 204 a.swap(b); 205 } 206 207 template<typename T> inline 208 bool operator==(T* p, const ::scoped_array<T>& b) { 209 return p == b.get(); 210 } 211 212 template<typename T> inline 213 bool operator!=(T* p, const ::scoped_array<T>& b) { 214 return p != b.get(); 215 } 216 217 218 // This class wraps the c library function free() in a class that can be 219 // passed as a template argument to scoped_ptr_malloc below. 220 class ScopedPtrMallocFree { 221 public: 222 inline void operator()(void* x) const { 223 free(x); 224 } 225 }; 226 227 // scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a 228 // second template argument, the functor used to free the object. 229 230 template<typename T, typename FreeProc = ScopedPtrMallocFree> 231 class scoped_ptr_malloc { 232 private: 233 234 T* ptr; 235 236 scoped_ptr_malloc(scoped_ptr_malloc const &); 237 scoped_ptr_malloc & operator=(scoped_ptr_malloc const &); 238 239 public: 240 241 typedef T element_type; 242 243 explicit scoped_ptr_malloc(T* p = 0): ptr(p) {} 244 245 ~scoped_ptr_malloc() { 246 typedef char type_must_be_complete[sizeof(T)]; 247 free_((void*) ptr); 248 } 249 250 void reset(T* p = 0) { 251 typedef char type_must_be_complete[sizeof(T)]; 252 253 if (ptr != p) { 254 free_((void*) ptr); 255 ptr = p; 256 } 257 } 258 259 T& operator*() const { 260 assert(ptr != 0); 261 return *ptr; 262 } 263 264 T* operator->() const { 265 assert(ptr != 0); 266 return ptr; 267 } 268 269 bool operator==(T* p) const { 270 return ptr == p; 271 } 272 273 bool operator!=(T* p) const { 274 return ptr != p; 275 } 276 277 T* get() const { 278 return ptr; 279 } 280 281 void swap(scoped_ptr_malloc & b) { 282 T* tmp = b.ptr; 283 b.ptr = ptr; 284 ptr = tmp; 285 } 286 287 T* release() { 288 T* tmp = ptr; 289 ptr = 0; 290 return tmp; 291 } 292 293 private: 294 295 // no reason to use these: each scoped_ptr_malloc should have its own object 296 template <typename U, typename GP> 297 bool operator==(scoped_ptr_malloc<U, GP> const& p) const; 298 template <typename U, typename GP> 299 bool operator!=(scoped_ptr_malloc<U, GP> const& p) const; 300 301 static FreeProc const free_; 302 }; 303 304 template<typename T, typename FP> 305 FP const scoped_ptr_malloc<T,FP>::free_ = FP(); 306 307 template<typename T, typename FP> inline 308 void swap(scoped_ptr_malloc<T,FP>& a, scoped_ptr_malloc<T,FP>& b) { 309 a.swap(b); 310 } 311 312 template<typename T, typename FP> inline 313 bool operator==(T* p, const scoped_ptr_malloc<T,FP>& b) { 314 return p == b.get(); 315 } 316 317 template<typename T, typename FP> inline 318 bool operator!=(T* p, const scoped_ptr_malloc<T,FP>& b) { 319 return p != b.get(); 320 } 321 322 #endif // #ifndef BASE_SCOPED_PTR_H 323