Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef TCG_UNIQUE_PTR_H
Toshihiro Shimizu 890ddd
#define TCG_UNIQUE_PTR_H
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// tcg includes
Toshihiro Shimizu 890ddd
#include "traits.h"
Toshihiro Shimizu 890ddd
#include "base.h"
Toshihiro Shimizu 890ddd
#include "deleter_types.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// STD includes
Toshihiro Shimizu 890ddd
#include "assert.h"
Toshihiro Shimizu 890ddd
#include <utility></utility>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace tcg
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************************
Toshihiro Shimizu 890ddd
//    unique_ptr  definition
Toshihiro Shimizu 890ddd
//**********************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  \brief    The unique_ptr class is a C++03 compatibility class that implements
Toshihiro Shimizu 890ddd
            a \a noncopyable smart pointer, similarly to \p boost::scoped_ptr,
Toshihiro Shimizu 890ddd
            but accepting a custom deleter type as template parameter.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  \details  \par  Properties
Toshihiro Shimizu 890ddd
            This class provides the following features:
Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
                  
  • It's noncopyable, like \p boost::scoped_ptr.
  • Toshihiro Shimizu 890ddd
                  
  • Unlike \p boost::scoped_ptr, it provides the release() method.
  • Toshihiro Shimizu 890ddd
                  
  • Arrays are valid template types - so <tt>tcg::unique_ptr<int []=""></int></tt>
  • Toshihiro Shimizu 890ddd
                      is accepted and works as expected.
    Toshihiro Shimizu 890ddd
                  
  • Like \p std::unique_ptr, it accepts custom \a inheritable deallocators.
  • Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
                \par  Incomplete types
    Toshihiro Shimizu 890ddd
                Like \p boost::scoped_ptr, incomplete types are accepted as template
    Toshihiro Shimizu 890ddd
                parameter, \a provided their definition is completed by the time the destructor
    Toshihiro Shimizu 890ddd
                is invoked. In particular, pointers to incomplete types \b must be stored in
    Toshihiro Shimizu 890ddd
                classes whose destructor is defined in an implementation file - and remember
    Toshihiro Shimizu 890ddd
                that compiler-generated destructors are always implicitly inlined.
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
                \par  Type erasure
    Toshihiro Shimizu 890ddd
                Unlike shared_ptr, this class does not employ type erasure
    Toshihiro Shimizu 890ddd
                on the deleter object - which is an explicit template argument by
    Toshihiro Shimizu 890ddd
                default. This means that the pointed object type must be \b complete
    Toshihiro Shimizu 890ddd
                at the moment the \p unique_ptr is destroyed, \a except if the
    Toshihiro Shimizu 890ddd
                supplied deleter is type-erased on its own.
    Toshihiro Shimizu 890ddd
     
    Toshihiro Shimizu 890ddd
      \remark   The C++11 class \p std::unique_ptr should be preferred, if possible.
    Toshihiro Shimizu 890ddd
    */
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    template <typename d="typename" t,="" tcg::deleter<t="" typename="">></typename>
    Toshihiro Shimizu 890ddd
    class unique_ptr : private D // Empty Base Optimization
    Toshihiro Shimizu 890ddd
    {
    Toshihiro Shimizu 890ddd
    public:
    Toshihiro Shimizu 890ddd
    	typedef typename tcg::traits<t>::element_type element_type;</t>
    Toshihiro Shimizu 890ddd
    	typedef typename tcg::traits<element_type>::pointer_type ptr_type;</element_type>
    Toshihiro Shimizu 890ddd
    	typedef typename tcg::traits<element_type>::reference_type ref_type;</element_type>
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    public:
    Toshihiro Shimizu 890ddd
    	explicit unique_ptr(ptr_type ptr = ptr_type()) // Explicit unary constructors
    Toshihiro Shimizu 890ddd
    		: m_ptr(ptr)
    Toshihiro Shimizu 890ddd
    	{
    Toshihiro Shimizu 890ddd
    	}
    Toshihiro Shimizu 890ddd
    	explicit unique_ptr(D d) : m_ptr(), D(d) {} //
    Toshihiro Shimizu 890ddd
    	unique_ptr(ptr_type ptr, D d) : m_ptr(ptr), D(d) {}
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    	~unique_ptr() { D::operator()(m_ptr); }
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    	friend void swap(unique_ptr &a, unique_ptr &b)
    Toshihiro Shimizu 890ddd
    	{
    Toshihiro Shimizu 890ddd
    		using std::swap;
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    		swap(static_cast<d &="">(a), static_cast<d &="">(b));</d></d>
    Toshihiro Shimizu 890ddd
    		swap(a.m_ptr, b.m_ptr);
    Toshihiro Shimizu 890ddd
    	}
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    	// Explicitly disabled (safe) conversion to bool - although
    Toshihiro Shimizu 890ddd
    	// std::unique_ptr could support it, that would just add overhead.
    Toshihiro Shimizu 890ddd
    	// It's also not compatible with other C++03 smart pointers.
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    	//typedef ptr_type unique_ptr::*                                 bool_type;
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    	//operator bool_type() const                                     // Safe bool idiom
    Toshihiro Shimizu 890ddd
    	//  { return m_ptr ? &unique_ptr::m_ptr : 0; }                   // additional branching!
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    	ptr_type operator->() const { return m_ptr; }
    Toshihiro Shimizu 890ddd
    	ref_type operator*() const { return *m_ptr; }
    Toshihiro Shimizu 890ddd
    	ref_type operator[](size_t idx) const
    Toshihiro Shimizu 890ddd
    	{
    Toshihiro Shimizu 890ddd
    		return m_ptr[idx];
    Toshihiro Shimizu 890ddd
    	}
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    	void reset(ptr_type ptr = ptr_type())
    Toshihiro Shimizu 890ddd
    	{
    Toshihiro Shimizu 890ddd
    		D::operator()(m_ptr);
    Toshihiro Shimizu 890ddd
    		m_ptr = ptr;
    Toshihiro Shimizu 890ddd
    	}
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    	void reset(ptr_type ptr, D d)
    Toshihiro Shimizu 890ddd
    	{
    Toshihiro Shimizu 890ddd
    		reset(ptr);
    Toshihiro Shimizu 890ddd
    		D::operator=(d);
    Toshihiro Shimizu 890ddd
    	}
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    	ptr_type release()
    Toshihiro Shimizu 890ddd
    	{
    Toshihiro Shimizu 890ddd
    		ptr_type ptr = m_ptr;
    Toshihiro Shimizu 890ddd
    		m_ptr = ptr_type();
    Toshihiro Shimizu 890ddd
    		return ptr;
    Toshihiro Shimizu 890ddd
    	}
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    	const ptr_type get() const { return m_ptr; }
    Toshihiro Shimizu 890ddd
    	ptr_type get() { return m_ptr; }
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    private:
    Toshihiro Shimizu 890ddd
    	ptr_type m_ptr;
    Toshihiro Shimizu 890ddd
    };
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    } // namespace tcg
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    #endif // TCG_UNIQUE_PTR_H