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