/////////////////////////////////////////////////////////////////////////////// // unique_ptr.hpp header file // // Copyright 2009 Howard Hinnant, Ion Gaztañaga. // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // See http://www.boost.org/libs/foreach for documentation // This is a C++03 emulation of std::unique_ptr placed in namespace boost. // Reference http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2800.pdf // for the latest unique_ptr specification, and // reference http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html // for any pending issues against this specification. #ifndef UNIQUE_PTR_HPP #define UNIQUE_PTR_HPP #include #include #include #include #include namespace boost { namespace detail_unique_ptr { typedef char one; struct two {one _[2];}; // An is_convertible that considers From an rvalue (consistent with C++0X). // This is a simplified version neglecting the types function, array, void and abstract types // I had to make a special case out of is_convertible to make move-only // types happy. namespace is_conv_imp { template one test1(const T&); template two test1(...); template one test2(T); template two test2(...); template T source(); } template struct is_convertible { static const bool value = sizeof(is_conv_imp::test1(is_conv_imp::source())) == 1; }; template struct is_convertible { static const bool value = sizeof(is_conv_imp::test2(is_conv_imp::source())) == 1; }; template struct identity { typedef T type; }; } // detail_unique_ptr namespace detail_unique_ptr { // A move-aware but stripped-down compressed_pair which only optimizes storage for T2 template ::value> class unique_ptr_storage { T1 t1_; T2 t2_; typedef typename add_reference::type T2_reference; typedef typename add_reference::type T2_const_reference; unique_ptr_storage(const unique_ptr_storage&); unique_ptr_storage& operator=(const unique_ptr_storage&); public: operator rv() {return rv(*this);} unique_ptr_storage() : t1_(), t2_() {} explicit unique_ptr_storage(T1 t1) : t1_(move(t1)), t2_() {} unique_ptr_storage(T1 t1, T2 t2) : t1_(move(t1)), t2_(forward(t2)) {} T1& first() {return t1_;} const T1& first() const {return t1_;} T2_reference second() {return t2_;} T2_const_reference second() const {return t2_;} }; template class unique_ptr_storage : private T2 { T1 t1_; typedef T2 t2_; unique_ptr_storage(const unique_ptr_storage&); unique_ptr_storage& operator=(const unique_ptr_storage&); public: operator rv() {return rv(*this);} unique_ptr_storage() : t1_() {} explicit unique_ptr_storage(T1 t1) : t1_(move(t1)) {} unique_ptr_storage(T1 t1, T2 t2) : t2_(move(t2)), t1_(move(t1)) {} T1& first() {return t1_;} const T1& first() const {return t1_;} T2& second() {return *this;} const T2& second() const {return *this;} }; template inline void swap(unique_ptr_storage& x, unique_ptr_storage& y) { using std::swap; swap(x.first(), y.first()); swap(x.second(), y.second()); } } // detail_unique_ptr template struct default_delete { default_delete() {} template default_delete(const default_delete&, typename enable_if_c::value>::type* = 0) {} void operator()(T* ptr) const { BOOST_STATIC_ASSERT(sizeof(T) > 0); delete ptr; } }; template struct default_delete { void operator()(T* ptr) const { BOOST_STATIC_ASSERT(sizeof(T) > 0); delete [] ptr; } private: template void operator()(U*) const; }; namespace detail_unique_ptr { namespace pointer_type_imp { template static two test(...); template static one test(typename U::pointer* = 0); } // pointer_type_imp template struct has_pointer_type { static const bool value = sizeof(pointer_type_imp::test(0)) == 1; }; namespace pointer_type_imp { template ::value> struct pointer_type { typedef typename D::pointer type; }; template struct pointer_type { typedef T* type; }; } // pointer_type_imp template struct pointer_type { typedef typename pointer_type_imp::pointer_type::type>::type type; }; } // detail_unique_ptr template > class unique_ptr { public: typedef T element_type; typedef D deleter_type; typedef typename detail_unique_ptr::pointer_type::type pointer; private: BOOST_MOVABLE_BUT_NOT_COPYABLE(unique_ptr) detail_unique_ptr::unique_ptr_storage ptr_; typedef typename add_reference::type deleter_reference; typedef typename add_reference::type deleter_const_reference; struct nat {int for_bool_;}; public: unique_ptr(BOOST_RV_REF(unique_ptr) r) : ptr_(r.release(), r.get_deleter()) { } unique_ptr& operator=(BOOST_RV_REF(unique_ptr) r) { if (this != &r) { reset(r.release()); ptr_.second() = move(r.get_deleter()); } return *this; } unique_ptr() { BOOST_STATIC_ASSERT(!is_reference::value); BOOST_STATIC_ASSERT(!is_pointer::value); } explicit unique_ptr(pointer p) : ptr_(p) { BOOST_STATIC_ASSERT(!is_reference::value); BOOST_STATIC_ASSERT(!is_pointer::value); } unique_ptr(pointer p, typename mpl::if_, volatile typename remove_reference::type&, D>::type d) : ptr_(move(p), forward(const_cast::type>(d))) {} template unique_ptr(unique_ptr u, typename enable_if_c < !boost::is_array::value && detail_unique_ptr::is_convertible::pointer, pointer>::value && detail_unique_ptr::is_convertible::value && ( !is_reference::value || is_same::value ) >::type* = 0) : ptr_(u.release(), forward(forward(u.get_deleter()))) {} ~unique_ptr() {reset();} unique_ptr& operator=(int nat::*) { reset(); return *this; } template unique_ptr& operator=(unique_ptr u) { reset(u.release()); ptr_.second() = move(u.get_deleter()); return *this; } typename add_reference::type operator*() const {return *get();} pointer operator->() const {return get();} pointer get() const {return ptr_.first();} deleter_reference get_deleter() {return ptr_.second();} deleter_const_reference get_deleter() const {return ptr_.second();} operator int nat::*() const {return get() ? &nat::for_bool_ : 0;} void reset(pointer p = pointer()) { pointer t = get(); if (t != pointer()) get_deleter()(t); ptr_.first() = p; } pointer release() { pointer tmp = get(); ptr_.first() = pointer(); return tmp; } void swap(unique_ptr& u) {detail_unique_ptr::swap(ptr_, u.ptr_);} }; template class unique_ptr { public: typedef T element_type; typedef D deleter_type; typedef typename detail_unique_ptr::pointer_type::type pointer; private: BOOST_MOVABLE_BUT_NOT_COPYABLE(unique_ptr) detail_unique_ptr::unique_ptr_storage ptr_; typedef typename add_reference::type deleter_reference; typedef typename add_reference::type deleter_const_reference; struct nat {int for_bool_;}; public: unique_ptr(BOOST_RV_REF(unique_ptr) r) : ptr_(r.release(), r.get_deleter()) {} unique_ptr& operator=(BOOST_RV_REF(unique_ptr) r) { reset(r.release()); ptr_.second() = move(r.get_deleter()); return *this; } unique_ptr() { BOOST_STATIC_ASSERT(!is_reference::value); BOOST_STATIC_ASSERT(!is_pointer::value); } explicit unique_ptr(pointer p) : ptr_(p) { BOOST_STATIC_ASSERT(!is_reference::value); BOOST_STATIC_ASSERT(!is_pointer::value); } unique_ptr(pointer p, typename mpl::if_, volatile typename remove_reference::type&, D>::type d) : ptr_(move(p), forward(const_cast::type>(d))) {} ~unique_ptr() {reset();} T& operator[](size_t i) const {return get()[i];} pointer get() const {return ptr_.first();} deleter_reference get_deleter() {return ptr_.second();} deleter_const_reference get_deleter() const {return ptr_.second();} operator int nat::*() const {return get() ? &nat::for_bool_ : 0;} void reset(pointer p = pointer()) { pointer t = get(); if (t != pointer()) get_deleter()(t); ptr_.first() = p; } pointer release() { pointer tmp = get(); ptr_.first() = pointer(); return tmp; } void swap(unique_ptr& u) {detail_unique_ptr::swap(ptr_, u.ptr_);} private: template explicit unique_ptr(U, typename enable_if_c::value>::type* = 0); template unique_ptr(U, typename mpl::if_, volatile typename remove_reference::type&, D>::type, typename enable_if_c::value>::type* = 0); }; template inline void swap(unique_ptr& x, unique_ptr& y) { x.swap(y); } template inline bool operator==(const unique_ptr& x, const unique_ptr& y) { return x.get() == y.get(); } template inline bool operator!=(const unique_ptr& x, const unique_ptr& y) { return !(x == y); } template inline bool operator<(const unique_ptr& x, const unique_ptr& y) { return x.get() < y.get(); } template inline bool operator<=(const unique_ptr& x, const unique_ptr& y) { return !(y < x); } template inline bool operator>(const unique_ptr& x, const unique_ptr& y) { return y < x; } template inline bool operator>=(const unique_ptr& x, const unique_ptr& y) { return !(x < y); } } // boost #endif // UNIQUE_PTR_HPP