1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #ifndef INCLUDED_O3TL_HEAP_PTR_HXX 29 #define INCLUDED_O3TL_HEAP_PTR_HXX 30 31 32 #include <boost/assert.hpp> 33 #include <boost/checked_delete.hpp> 34 35 36 namespace o3tl 37 { 38 /** heap_ptr<> owns an object on the heap, which will be automatically 39 deleted, when ~heap_ptr<>() is called. 40 41 Applicability 42 ------------- 43 heap_ptr<> can be used for class members on the heap. 44 - One cannot forget to delete them in the destructor. 45 - Constness will be transfered from the owning instance. 46 47 heap_ptr<> can also be used as smart pointer in function bodies to 48 ensure exception safety. 49 50 Special Characteristics 51 ----------------------- 52 - heap_ptr<> transfers constness from the owning object to 53 the pointed to object. Such it behaves like if *get() would be 54 a normal member of the owning object, not a pointer member. 55 This is preferable to the normal pointer behaviour, because 56 if an object is owned by another one, it is normally part of 57 its state. 58 59 - heap_ptr<> provides a ->release() function 60 61 - For reasons of simplicity and portability ->is() 62 is preferred over the safe-bool idiom. 63 64 Copyability 65 ----------- 66 heap_ptr is non copyable. 67 - It forbids the copyconstructor and operator=(self). 68 69 - Owning classes will automatically be non copyable, if they do not 70 redefine those two functions themselves. 71 72 Incomplete Types 73 ---------------- 74 heap_ptr<> also works with incomplete types. You only need to write 75 class T; 76 but need not include <T>.hxx. 77 78 If you use heap_ptr<> with an incomplete type, the owning class 79 needs to define a non-inline destructor. Else the compiler will 80 complain. 81 */ 82 template <class T> 83 class heap_ptr 84 { 85 public: 86 typedef T element_type; /// Provided for generic programming. 87 typedef heap_ptr<T> self; 88 89 #ifndef __SUNPRO_CC 90 typedef T * (self::* safe_bool )(); 91 #endif 92 93 /// Now, pass_heapObject is owned by this. 94 explicit heap_ptr( 95 T * pass_heapObject = 0 ); 96 ~heap_ptr(); 97 98 99 /** Identical to reset(), except of the return value. 100 @see heap_ptr<>::reset() 101 */ 102 self & operator=( 103 T * pass_heapObject ); 104 const T & operator*() const; 105 T & operator*(); 106 const T * operator->() const; 107 T * operator->(); 108 109 /// True, if pHeapObject != 0. 110 #ifndef __SUNPRO_CC 111 operator safe_bool() const; 112 #else // workaround opt bug of Sun C++ compiler, when compiling with -xO3 113 operator bool() const; 114 #endif 115 116 117 /** This deletes any prevoiusly existing ->pHeapObject. 118 Now, pass_heapObject, if != 0, is owned by this. 119 120 @onerror 121 Ignores self-assignment. 122 Such, multiple assignment of the same pointer to the same 123 instance of heap_ptr<> is possible (though not recommended). 124 */ 125 void reset( 126 T * pass_heapObject ); 127 /** @return An object on the heap that must be deleted by the caller, 128 or 0. 129 130 @postcond get() == 0; 131 */ 132 T * release(); 133 void swap( 134 self & io_other ); 135 136 /// True, if pHeapObject != 0. 137 bool is() const; 138 const T * get() const; 139 T * get(); 140 141 private: 142 // Forbidden functions: 143 heap_ptr( const self & ); /// Prevent copies. 144 self & operator=( const self & ); /// Prevent copies. 145 146 /// @attention Does not set ->pHeapObject = 0. 147 void internal_delete(); 148 149 // DATA 150 /// Will be deleted, when *this is destroyed. 151 T * pHeapObject; 152 }; 153 154 155 /** Supports the semantic of std::swap(). Provided as an aid to 156 generic programming. 157 */ 158 template<class T> 159 inline void 160 swap( heap_ptr<T> & io_a, 161 heap_ptr<T> & io_b ) 162 { 163 io_a.swap(io_b); 164 } 165 166 167 168 // IMPLEMENTATION 169 170 template <class T> 171 inline void 172 heap_ptr<T>::internal_delete() 173 { 174 ::boost::checked_delete(pHeapObject); 175 176 // Do not set pHeapObject to 0, because 177 // that is reset to a value in all code 178 // where internal_delete() is used. 179 } 180 181 template <class T> 182 inline 183 heap_ptr<T>::heap_ptr( T * pass_heapObject ) 184 : pHeapObject(pass_heapObject) 185 { 186 } 187 188 template <class T> 189 inline 190 heap_ptr<T>::~heap_ptr() 191 { 192 internal_delete(); 193 } 194 195 template <class T> 196 inline heap_ptr<T> & 197 heap_ptr<T>::operator=(T * pass_heapObject) 198 { 199 reset(pass_heapObject); 200 return *this; 201 } 202 203 template <class T> 204 inline const T & 205 heap_ptr<T>::operator*() const 206 { 207 BOOST_ASSERT( pHeapObject != 0 208 && "Accessing a heap_ptr<>(0)." ); 209 return *pHeapObject; 210 } 211 212 template <class T> 213 inline T & 214 heap_ptr<T>::operator*() 215 { 216 BOOST_ASSERT( pHeapObject != 0 217 && "Accessing a heap_ptr<>(0)." ); 218 return *pHeapObject; 219 } 220 221 template <class T> 222 inline const T * 223 heap_ptr<T>::operator->() const 224 { 225 return pHeapObject; 226 } 227 228 template <class T> 229 inline T * 230 heap_ptr<T>::operator->() 231 { 232 return pHeapObject; 233 } 234 235 #ifndef __SUNPRO_CC 236 237 template <class T> 238 inline 239 heap_ptr<T>::operator typename heap_ptr<T>::safe_bool() const 240 { 241 return is() 242 ? safe_bool(&self::get) 243 : safe_bool(0); 244 } 245 246 #else 247 248 template <class T> 249 inline heap_ptr<T>::operator bool() const 250 { 251 return is(); 252 } 253 254 #endif // !defined(__SUNPRO_CC) 255 256 257 258 template <class T> 259 void 260 heap_ptr<T>::reset(T * pass_heapObject) 261 { 262 if ( pHeapObject != 0 263 && pHeapObject == pass_heapObject) 264 return; 265 266 internal_delete(); 267 pHeapObject = pass_heapObject; 268 } 269 270 template <class T> 271 T * 272 heap_ptr<T>::release() 273 { 274 T * ret = pHeapObject; 275 pHeapObject = 0; 276 return ret; 277 } 278 279 template <class T> 280 void 281 heap_ptr<T>::swap(self & io_other) 282 { 283 T * temp = io_other.pHeapObject; 284 io_other.pHeapObject = pHeapObject; 285 pHeapObject = temp; 286 } 287 288 template <class T> 289 inline bool 290 heap_ptr<T>::is() const 291 { 292 return pHeapObject != 0; 293 } 294 295 template <class T> 296 inline const T * 297 heap_ptr<T>::get() const 298 { 299 return pHeapObject; 300 } 301 302 template <class T> 303 inline T * 304 heap_ptr<T>::get() 305 { 306 return pHeapObject; 307 } 308 309 310 } // namespace o3tl 311 #endif 312