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