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