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