blob: 25541f16a429f7145e6f13aa20b1207bf37c40be [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#ifndef INCLUDED_O3TL_HEAP_PTR_HXX
#define INCLUDED_O3TL_HEAP_PTR_HXX
#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
namespace o3tl
{
/** heap_ptr<> owns an object on the heap, which will be automatically
deleted, when ~heap_ptr<>() is called.
Applicability
-------------
heap_ptr<> can be used for class members on the heap.
- One cannot forget to delete them in the destructor.
- Constness will be transfered from the owning instance.
heap_ptr<> can also be used as smart pointer in function bodies to
ensure exception safety.
Special Characteristics
-----------------------
- heap_ptr<> transfers constness from the owning object to
the pointed to object. Such it behaves like if *get() would be
a normal member of the owning object, not a pointer member.
This is preferable to the normal pointer behaviour, because
if an object is owned by another one, it is normally part of
its state.
- heap_ptr<> provides a ->release() function
- For reasons of simplicity and portability ->is()
is preferred over the safe-bool idiom.
Copyability
-----------
heap_ptr is non copyable.
- It forbids the copyconstructor and operator=(self).
- Owning classes will automatically be non copyable, if they do not
redefine those two functions themselves.
Incomplete Types
----------------
heap_ptr<> also works with incomplete types. You only need to write
class T;
but need not include <T>.hxx.
If you use heap_ptr<> with an incomplete type, the owning class
needs to define a non-inline destructor. Else the compiler will
complain.
*/
template <class T>
class heap_ptr
{
public:
typedef T element_type; /// Provided for generic programming.
typedef heap_ptr<T> self;
#ifndef __SUNPRO_CC
typedef T * (self::* safe_bool )();
#endif
/// Now, pass_heapObject is owned by this.
explicit heap_ptr(
T * pass_heapObject = 0 );
~heap_ptr();
/** Identical to reset(), except of the return value.
@see heap_ptr<>::reset()
*/
self & operator=(
T * pass_heapObject );
const T & operator*() const;
T & operator*();
const T * operator->() const;
T * operator->();
/// True, if pHeapObject != 0.
#ifndef __SUNPRO_CC
operator safe_bool() const;
#else // workaround opt bug of Sun C++ compiler, when compiling with -xO3
operator bool() const;
#endif
/** This deletes any prevoiusly existing ->pHeapObject.
Now, pass_heapObject, if != 0, is owned by this.
@onerror
Ignores self-assignment.
Such, multiple assignment of the same pointer to the same
instance of heap_ptr<> is possible (though not recommended).
*/
void reset(
T * pass_heapObject );
/** @return An object on the heap that must be deleted by the caller,
or 0.
@postcond get() == 0;
*/
T * release();
void swap(
self & io_other );
/// True, if pHeapObject != 0.
bool is() const;
const T * get() const;
T * get();
private:
// Forbidden functions:
heap_ptr( const self & ); /// Prevent copies.
self & operator=( const self & ); /// Prevent copies.
/// @attention Does not set ->pHeapObject = 0.
void internal_delete();
// DATA
/// Will be deleted, when *this is destroyed.
T * pHeapObject;
};
/** Supports the semantic of std::swap(). Provided as an aid to
generic programming.
*/
template<class T>
inline void
swap( heap_ptr<T> & io_a,
heap_ptr<T> & io_b )
{
io_a.swap(io_b);
}
// IMPLEMENTATION
template <class T>
inline void
heap_ptr<T>::internal_delete()
{
::boost::checked_delete(pHeapObject);
// Do not set pHeapObject to 0, because
// that is reset to a value in all code
// where internal_delete() is used.
}
template <class T>
inline
heap_ptr<T>::heap_ptr( T * pass_heapObject )
: pHeapObject(pass_heapObject)
{
}
template <class T>
inline
heap_ptr<T>::~heap_ptr()
{
internal_delete();
}
template <class T>
inline heap_ptr<T> &
heap_ptr<T>::operator=(T * pass_heapObject)
{
reset(pass_heapObject);
return *this;
}
template <class T>
inline const T &
heap_ptr<T>::operator*() const
{
BOOST_ASSERT( pHeapObject != 0
&& "Accessing a heap_ptr<>(0)." );
return *pHeapObject;
}
template <class T>
inline T &
heap_ptr<T>::operator*()
{
BOOST_ASSERT( pHeapObject != 0
&& "Accessing a heap_ptr<>(0)." );
return *pHeapObject;
}
template <class T>
inline const T *
heap_ptr<T>::operator->() const
{
return pHeapObject;
}
template <class T>
inline T *
heap_ptr<T>::operator->()
{
return pHeapObject;
}
#ifndef __SUNPRO_CC
template <class T>
inline
heap_ptr<T>::operator typename heap_ptr<T>::safe_bool() const
{
return is()
? safe_bool(&self::get)
: safe_bool(0);
}
#else
template <class T>
inline heap_ptr<T>::operator bool() const
{
return is();
}
#endif // !defined(__SUNPRO_CC)
template <class T>
void
heap_ptr<T>::reset(T * pass_heapObject)
{
if ( pHeapObject != 0
&& pHeapObject == pass_heapObject)
return;
internal_delete();
pHeapObject = pass_heapObject;
}
template <class T>
T *
heap_ptr<T>::release()
{
T * ret = pHeapObject;
pHeapObject = 0;
return ret;
}
template <class T>
void
heap_ptr<T>::swap(self & io_other)
{
T * temp = io_other.pHeapObject;
io_other.pHeapObject = pHeapObject;
pHeapObject = temp;
}
template <class T>
inline bool
heap_ptr<T>::is() const
{
return pHeapObject != 0;
}
template <class T>
inline const T *
heap_ptr<T>::get() const
{
return pHeapObject;
}
template <class T>
inline T *
heap_ptr<T>::get()
{
return pHeapObject;
}
} // namespace o3tl
#endif