office-gobmx/include/o3tl/heap_ptr.hxx
Stephan Bergmann 75e0fe06ac Extend o3tl::heap_ptr to support arrays
Change-Id: I546afcb626e27f6f1115715829779fc0b657548e
2014-06-06 11:13:07 +02:00

283 lines
7.3 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* 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 .
*/
#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 transferred 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 Deleter = boost::checked_deleter<T> >
class heap_ptr
{
public:
typedef T element_type; /// Provided for generic programming.
typedef heap_ptr<T, Deleter> self;
typedef T * (self::* safe_bool )();
/// 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->();
operator safe_bool() const;
/** 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, class Deleter>
inline void
swap( heap_ptr<T, Deleter> & io_a,
heap_ptr<T, Deleter> & io_b )
{
io_a.swap(io_b);
}
// IMPLEMENTATION
template <class T, class Deleter>
inline void
heap_ptr<T, Deleter>::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, class Deleter>
inline
heap_ptr<T, Deleter>::heap_ptr( T * pass_heapObject )
: pHeapObject(pass_heapObject)
{
}
template <class T, class Deleter>
inline
heap_ptr<T, Deleter>::~heap_ptr()
{
internal_delete();
}
template <class T, class Deleter>
inline heap_ptr<T, Deleter> &
heap_ptr<T, Deleter>::operator=(T * pass_heapObject)
{
reset(pass_heapObject);
return *this;
}
template <class T, class Deleter>
inline const T &
heap_ptr<T, Deleter>::operator*() const
{
BOOST_ASSERT( pHeapObject != 0
&& "Accessing a heap_ptr<>(0)." );
return *pHeapObject;
}
template <class T, class Deleter>
inline T &
heap_ptr<T, Deleter>::operator*()
{
BOOST_ASSERT( pHeapObject != 0
&& "Accessing a heap_ptr<>(0)." );
return *pHeapObject;
}
template <class T, class Deleter>
inline const T *
heap_ptr<T, Deleter>::operator->() const
{
return pHeapObject;
}
template <class T, class Deleter>
inline T *
heap_ptr<T, Deleter>::operator->()
{
return pHeapObject;
}
template <class T, class Deleter>
inline
heap_ptr<T, Deleter>::operator typename heap_ptr<T, Deleter>::safe_bool() const
{
return is()
? safe_bool(&self::get)
: safe_bool(0);
}
template <class T, class Deleter>
void
heap_ptr<T, Deleter>::reset(T * pass_heapObject)
{
if ( pHeapObject != 0
&& pHeapObject == pass_heapObject)
return;
internal_delete();
pHeapObject = pass_heapObject;
}
template <class T, class Deleter>
T *
heap_ptr<T, Deleter>::release()
{
T * ret = pHeapObject;
pHeapObject = 0;
return ret;
}
template <class T, class Deleter>
void
heap_ptr<T, Deleter>::swap(self & io_other)
{
T * temp = io_other.pHeapObject;
io_other.pHeapObject = pHeapObject;
pHeapObject = temp;
}
template <class T, class Deleter>
inline bool
heap_ptr<T, Deleter>::is() const
{
return pHeapObject != 0;
}
template <class T, class Deleter>
inline const T *
heap_ptr<T, Deleter>::get() const
{
return pHeapObject;
}
template <class T, class Deleter>
inline T *
heap_ptr<T, Deleter>::get()
{
return pHeapObject;
}
} // namespace o3tl
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */