Shinya Kitaoka 810553
#pragma once
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
Shinya Kitaoka 120a6e
namespace tcg {
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.
  • Shinya Kitaoka 120a6e
                  
  • Unlike \p boost::scoped_ptr, it provides the release()
  • Shinya Kitaoka 120a6e
    method.
    Shinya Kitaoka 120a6e
                  
  • Arrays are valid template types - so <tt>tcg::unique_ptr</tt>
  • Shinya Kitaoka 120a6e
    []>
    Toshihiro Shimizu 890ddd
                      is accepted and works as expected.
    Shinya Kitaoka 120a6e
                  
  • Like \p std::unique_ptr, it accepts custom \a inheritable
  • Shinya Kitaoka 120a6e
    deallocators.
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
                \par  Incomplete types
    Toshihiro Shimizu 890ddd
                Like \p boost::scoped_ptr, incomplete types are accepted as template
    Shinya Kitaoka 120a6e
                parameter, \a provided their definition is completed by the time the
    Shinya Kitaoka 120a6e
    destructor
    Shinya Kitaoka 120a6e
                is invoked. In particular, pointers to incomplete types \b must be
    Shinya Kitaoka 120a6e
    stored in
    Shinya Kitaoka 120a6e
                classes whose destructor is defined in an implementation file - and
    Shinya Kitaoka 120a6e
    remember
    Shinya Kitaoka 120a6e
                that compiler-generated destructors are always implicitly
    Shinya Kitaoka 120a6e
    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.
    Shinya Kitaoka 120a6e
    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>
    Shinya Kitaoka 120a6e
    class unique_ptr : private D  // Empty Base Optimization
    Toshihiro Shimizu 890ddd
    {
    Toshihiro Shimizu 890ddd
    public:
    Shinya Kitaoka 120a6e
      typedef typename tcg::traits<t>::element_type element_type;</t>
    Shinya Kitaoka 120a6e
      typedef typename tcg::traits<element_type>::pointer_type ptr_type;</element_type>
    Shinya Kitaoka 120a6e
      typedef typename tcg::traits<element_type>::reference_type ref_type;</element_type>
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    public:
    Shinya Kitaoka 120a6e
      explicit unique_ptr(ptr_type ptr = ptr_type())  // Explicit unary constructors
    Shinya Kitaoka 120a6e
          : m_ptr(ptr) {}
    Shinya Kitaoka 120a6e
      explicit unique_ptr(D d) : m_ptr(), D(d) {}  //
    Shinya Kitaoka 120a6e
      unique_ptr(ptr_type ptr, D d) : m_ptr(ptr), D(d) {}
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      ~unique_ptr() { D::operator()(m_ptr); }
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      friend void swap(unique_ptr &a, unique_ptr &b) {
    Shinya Kitaoka 120a6e
        using std::swap;
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
        swap(static_cast<d &="">(a), static_cast<d &="">(b));</d></d>
    Shinya Kitaoka 120a6e
        swap(a.m_ptr, b.m_ptr);
    Shinya Kitaoka 120a6e
      }
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      // Explicitly disabled (safe) conversion to bool - although
    Shinya Kitaoka 120a6e
      // std::unique_ptr could support it, that would just add overhead.
    Shinya Kitaoka 120a6e
      // It's also not compatible with other C++03 smart pointers.
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      // typedef ptr_type unique_ptr::*                                 bool_type;
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      // operator bool_type() const                                     // Safe bool
    Shinya Kitaoka 120a6e
      // idiom
    Shinya Kitaoka 120a6e
      //  { return m_ptr ? &unique_ptr::m_ptr : 0; }                   // additional
    Shinya Kitaoka 120a6e
      //  branching!
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      ptr_type operator->() const { return m_ptr; }
    Shinya Kitaoka 120a6e
      ref_type operator*() const { return *m_ptr; }
    Shinya Kitaoka 120a6e
      ref_type operator[](size_t idx) const { return m_ptr[idx]; }
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      void reset(ptr_type ptr = ptr_type()) {
    Shinya Kitaoka 120a6e
        D::operator()(m_ptr);
    Shinya Kitaoka 120a6e
        m_ptr = ptr;
    Shinya Kitaoka 120a6e
      }
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      void reset(ptr_type ptr, D d) {
    Shinya Kitaoka 120a6e
        reset(ptr);
    Shinya Kitaoka 120a6e
        D::operator=(d);
    Shinya Kitaoka 120a6e
      }
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      ptr_type release() {
    Shinya Kitaoka 120a6e
        ptr_type ptr = m_ptr;
    Shinya Kitaoka 120a6e
        m_ptr        = ptr_type();
    Shinya Kitaoka 120a6e
        return ptr;
    Shinya Kitaoka 120a6e
      }
    Shinya Kitaoka 120a6e
    Shinya Kitaoka 120a6e
      const ptr_type get() const { return m_ptr; }
    Shinya Kitaoka 120a6e
      ptr_type get() { return m_ptr; }
    Toshihiro Shimizu 890ddd
    Toshihiro Shimizu 890ddd
    private:
    Shinya Kitaoka 120a6e
      ptr_type m_ptr;
    Toshihiro Shimizu 890ddd
    };
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
    }  // namespace tcg
    Toshihiro Shimizu 890ddd
    Shinya Kitaoka 120a6e
    #endif  // TCG_UNIQUE_PTR_H