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 transferred 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
swap(heap_ptr<T> & io_a,heap_ptr<T> & io_b)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
internal_delete()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
heap_ptr(T * pass_heapObject)179 heap_ptr<T>::heap_ptr( T * pass_heapObject )
180 : pHeapObject(pass_heapObject)
181 {
182 }
183
184 template <class T>
185 inline
~heap_ptr()186 heap_ptr<T>::~heap_ptr()
187 {
188 internal_delete();
189 }
190
191 template <class T>
192 inline heap_ptr<T> &
operator =(T * pass_heapObject)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 &
operator *() const201 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 &
operator *()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 *
operator ->() const219 heap_ptr<T>::operator->() const
220 {
221 return pHeapObject;
222 }
223
224 template <class T>
225 inline T *
operator ->()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
reset(T * pass_heapObject)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 *
release()268 heap_ptr<T>::release()
269 {
270 T * ret = pHeapObject;
271 pHeapObject = 0;
272 return ret;
273 }
274
275 template <class T>
276 void
swap(self & io_other)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
is() const286 heap_ptr<T>::is() const
287 {
288 return pHeapObject != 0;
289 }
290
291 template <class T>
292 inline const T *
get() const293 heap_ptr<T>::get() const
294 {
295 return pHeapObject;
296 }
297
298 template <class T>
299 inline T *
get()300 heap_ptr<T>::get()
301 {
302 return pHeapObject;
303 }
304
305
306 } // namespace o3tl
307 #endif
308