xref: /aoo4110/main/o3tl/inc/o3tl/heap_ptr.hxx (revision b1cdbd2c)
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
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