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