Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // (C) Copyright Ion Gaztanaga 2014-2014. Distributed under the Boost Chris@102: // Software License, Version 1.0. (See accompanying file Chris@102: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@102: // Chris@102: // See http://www.boost.org/libs/move for documentation. Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: #ifndef BOOST_MOVE_UNIQUE_PTR_HPP_INCLUDED Chris@102: #define BOOST_MOVE_UNIQUE_PTR_HPP_INCLUDED Chris@102: Chris@102: #ifndef BOOST_CONFIG_HPP Chris@102: # include Chris@102: #endif Chris@102: # Chris@102: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@102: # pragma once Chris@102: #endif Chris@102: Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: Chris@102: #include //For std::nullptr_t and std::size_t Chris@102: Chris@102: //!\file Chris@102: //! Describes the smart pointer unique_ptr, a drop-in replacement for std::unique_ptr, Chris@102: //! usable also from C++03 compilers. Chris@102: //! Chris@102: //! Main differences from std::unique_ptr to avoid heavy dependencies, Chris@102: //! specially in C++03 compilers: Chris@102: //! - operator < uses pointer operator < instead of std::less. Chris@102: //! This avoids dependencies on std::common_type and std::less Chris@102: //! (/ headers. In C++03 this avoid pulling Boost.Typeof and other Chris@102: //! cascading dependencies. As in all Boost platforms operator < on raw pointers and Chris@102: //! other smart pointers provides strict weak ordering in practice this should not be a problem for users. Chris@102: //! - assignable from literal 0 for compilers without nullptr Chris@102: //! - unique_ptr is constructible and assignable from unique_ptr if Chris@102: //! cv-less T and cv-less U are the same type and T is more CV qualified than U. Chris@102: Chris@102: namespace boost{ Chris@102: namespace move_upd { Chris@102: Chris@102: //////////////////////////////////////////// Chris@102: // deleter types Chris@102: //////////////////////////////////////////// Chris@102: #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@102: template Chris@102: class is_noncopyable Chris@102: { Chris@102: typedef char true_t; Chris@102: class false_t { char dummy[2]; }; Chris@102: template static false_t dispatch(...); Chris@102: template static true_t dispatch(typename U::boost_move_no_copy_constructor_or_assign*); Chris@102: public: Chris@102: static const bool value = sizeof(dispatch(0)) == sizeof(true_t); Chris@102: }; Chris@102: #endif //defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@102: Chris@102: template Chris@102: struct deleter_types Chris@102: { Chris@102: typedef typename bmupmu::add_lvalue_reference::type del_ref; Chris@102: typedef typename bmupmu::add_const_lvalue_reference::type del_cref; Chris@102: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@102: typedef typename bmupmu::if_c Chris@102: < bmupmu::is_lvalue_reference::value, D, del_cref >::type deleter_arg_type1; Chris@102: typedef typename bmupmu::remove_reference::type && deleter_arg_type2; Chris@102: #else Chris@102: typedef typename bmupmu::if_c Chris@102: < is_noncopyable::value, bmupmu::nat, del_cref>::type non_ref_deleter_arg1; Chris@102: typedef typename bmupmu::if_c< bmupmu::is_lvalue_reference::value Chris@102: , D, non_ref_deleter_arg1 >::type deleter_arg_type1; Chris@102: typedef ::boost::rv & deleter_arg_type2; Chris@102: #endif Chris@102: }; Chris@102: Chris@102: //////////////////////////////////////////// Chris@102: // unique_ptr_data Chris@102: //////////////////////////////////////////// Chris@102: template ::value || bmupmu::is_reference::value > Chris@102: struct unique_ptr_data Chris@102: { Chris@102: typedef typename deleter_types::deleter_arg_type1 deleter_arg_type1; Chris@102: typedef typename deleter_types::del_ref del_ref; Chris@102: typedef typename deleter_types::del_cref del_cref; Chris@102: Chris@102: unique_ptr_data() BOOST_NOEXCEPT Chris@102: : m_p(), d() Chris@102: {} Chris@102: Chris@102: explicit unique_ptr_data(P p) BOOST_NOEXCEPT Chris@102: : m_p(p), d() Chris@102: {} Chris@102: Chris@102: unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT Chris@102: : m_p(p), d(d1) Chris@102: {} Chris@102: Chris@102: template Chris@102: unique_ptr_data(P p, BOOST_FWD_REF(U) d) BOOST_NOEXCEPT Chris@102: : m_p(p), d(::boost::forward(d)) Chris@102: {} Chris@102: Chris@102: del_ref deleter() { return d; } Chris@102: del_cref deleter() const{ return d; } Chris@102: Chris@102: P m_p; Chris@102: D d; Chris@102: Chris@102: private: Chris@102: unique_ptr_data& operator=(const unique_ptr_data&); Chris@102: unique_ptr_data(const unique_ptr_data&); Chris@102: }; Chris@102: Chris@102: template Chris@102: struct unique_ptr_data Chris@102: : private D Chris@102: { Chris@102: typedef typename deleter_types::deleter_arg_type1 deleter_arg_type1; Chris@102: typedef typename deleter_types::del_ref del_ref; Chris@102: typedef typename deleter_types::del_cref del_cref; Chris@102: Chris@102: unique_ptr_data() BOOST_NOEXCEPT Chris@102: : D(), m_p() Chris@102: {} Chris@102: Chris@102: explicit unique_ptr_data(P p) BOOST_NOEXCEPT Chris@102: : D(), m_p(p) Chris@102: {} Chris@102: Chris@102: unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT Chris@102: : D(d1), m_p(p) Chris@102: {} Chris@102: Chris@102: template Chris@102: unique_ptr_data(P p, BOOST_FWD_REF(U) d) BOOST_NOEXCEPT Chris@102: : D(::boost::forward(d)), m_p(p) Chris@102: {} Chris@102: Chris@102: del_ref deleter() BOOST_NOEXCEPT { return static_cast(*this); } Chris@102: del_cref deleter() const BOOST_NOEXCEPT { return static_cast(*this); } Chris@102: Chris@102: P m_p; Chris@102: Chris@102: private: Chris@102: unique_ptr_data& operator=(const unique_ptr_data&); Chris@102: unique_ptr_data(const unique_ptr_data&); Chris@102: }; Chris@102: Chris@102: //////////////////////////////////////////// Chris@102: // is_unique_ptr_convertible Chris@102: //////////////////////////////////////////// Chris@102: Chris@102: //Although non-standard, we avoid using pointer_traits Chris@102: //to avoid heavy dependencies Chris@102: template Chris@102: struct get_element_type Chris@102: { Chris@102: struct DefaultWrap { typedef bmupmu::natify element_type; }; Chris@102: template static char test(int, typename X::element_type*); Chris@102: template static int test(...); Chris@102: static const bool value = (1 == sizeof(test(0, 0))); Chris@102: typedef typename bmupmu::if_c::type::element_type type; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct get_element_type Chris@102: { Chris@102: typedef T type; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct get_cvelement Chris@102: : bmupmu::remove_cv::type> Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct is_same_cvelement_and_convertible Chris@102: { Chris@102: typedef typename bmupmu::remove_reference::type arg1; Chris@102: typedef typename bmupmu::remove_reference::type arg2; Chris@102: static const bool same_cvless = Chris@102: bmupmu::is_same::type,typename get_cvelement::type>::value; Chris@102: static const bool value = same_cvless && bmupmu::is_convertible::value; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct is_unique_ptr_convertible Chris@102: : is_same_cvelement_and_convertible Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct is_unique_ptr_convertible Chris@102: : bmupmu::is_convertible Chris@102: {}; Chris@102: Chris@102: //////////////////////////////////////// Chris@102: //// enable_up_moveconv_assign Chris@102: //////////////////////////////////////// Chris@102: Chris@102: template Chris@102: struct enable_up_ptr Chris@102: : bmupmu::enable_if_c< is_unique_ptr_convertible Chris@102: < bmupmu::is_array::value, FromPointer, ThisPointer>::value, Type> Chris@102: {}; Chris@102: Chris@102: //////////////////////////////////////// Chris@102: //// enable_up_moveconv_assign Chris@102: //////////////////////////////////////// Chris@102: Chris@102: template Chris@102: struct unique_moveconvert_assignable Chris@102: { Chris@102: static const bool value = (bmupmu::extent::value == bmupmu::extent::value) && is_unique_ptr_convertible Chris@102: < bmupmu::is_array::value Chris@102: , typename bmupmu::pointer_type::type, typename bmupmu::pointer_type::type>::value; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct unique_moveconvert_assignable Chris@102: : unique_moveconvert_assignable Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct enable_up_moveconv_assign Chris@102: : bmupmu::enable_if_c::value, Type> Chris@102: {}; Chris@102: Chris@102: //////////////////////////////////////// Chris@102: //// enable_up_moveconv_constr Chris@102: //////////////////////////////////////// Chris@102: Chris@102: template::value> Chris@102: struct unique_deleter_is_initializable Chris@102: : bmupmu::is_same Chris@102: {}; Chris@102: Chris@102: template Chris@102: class is_rvalue_convertible Chris@102: { Chris@102: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@102: typedef typename bmupmu::remove_reference::type&& t_from; Chris@102: #else Chris@102: typedef typename bmupmu::if_c Chris@102: < ::boost::has_move_emulation_enabled::value && !bmupmu::is_reference::value Chris@102: , ::boost::rv& Chris@102: , typename bmupmu::add_lvalue_reference::type Chris@102: >::type t_from; Chris@102: #endif Chris@102: Chris@102: typedef char true_t; Chris@102: class false_t { char dummy[2]; }; Chris@102: static false_t dispatch(...); Chris@102: static true_t dispatch(U); Chris@102: static t_from trigger(); Chris@102: public: Chris@102: static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t); Chris@102: }; Chris@102: Chris@102: template Chris@102: struct unique_deleter_is_initializable Chris@102: { Chris@102: #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@102: //Clang has some problems with is_rvalue_convertible with non-copyable types Chris@102: //so use intrinsic if available Chris@102: #if defined(BOOST_CLANG) Chris@102: #if __has_feature(is_convertible_to) Chris@102: static const bool value = __is_convertible_to(E, D); Chris@102: #else Chris@102: static const bool value = is_rvalue_convertible::value; Chris@102: #endif Chris@102: #else Chris@102: static const bool value = is_rvalue_convertible::value; Chris@102: #endif Chris@102: Chris@102: #else //!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@102: //No hope for compilers with move emulation for now. In several compilers is_convertible Chris@102: // leads to errors, so just move the Deleter and see if the conversion works Chris@102: static const bool value = true; /*is_rvalue_convertible::value*/ Chris@102: #endif Chris@102: }; Chris@102: Chris@102: template Chris@102: struct enable_up_moveconv_constr Chris@102: : bmupmu::enable_if_c::value && Chris@102: unique_deleter_is_initializable::value, Type> Chris@102: {}; Chris@102: Chris@102: } //namespace move_upd { Chris@102: Chris@102: namespace movelib { Chris@102: Chris@102: //! A unique pointer is an object that owns another object and Chris@102: //! manages that other object through a pointer. Chris@102: //! Chris@102: //! More precisely, a unique pointer is an object u that stores a pointer to a second object p and will dispose Chris@102: //! of p when u is itself destroyed (e.g., when leaving block scope). In this context, u is said to own p. Chris@102: //! Chris@102: //! The mechanism by which u disposes of p is known as p's associated deleter, a function object whose correct Chris@102: //! invocation results in p's appropriate disposition (typically its deletion). Chris@102: //! Chris@102: //! Let the notation u.p denote the pointer stored by u, and let u.d denote the associated deleter. Upon request, Chris@102: //! u can reset (replace) u.p and u.d with another pointer and deleter, but must properly dispose of its owned Chris@102: //! object via the associated deleter before such replacement is considered completed. Chris@102: //! Chris@102: //! Additionally, u can, upon request, transfer ownership to another unique pointer u2. Upon completion of Chris@102: //! such a transfer, the following postconditions hold: Chris@102: //! - u2.p is equal to the pre-transfer u.p, Chris@102: //! - u.p is equal to nullptr, and Chris@102: //! - if the pre-transfer u.d maintained state, such state has been transferred to u2.d. Chris@102: //! Chris@102: //! As in the case of a reset, u2 must properly dispose of its pre-transfer owned object via the pre-transfer Chris@102: //! associated deleter before the ownership transfer is considered complete. Chris@102: //! Chris@102: //! Each object of a type U instantiated from the unique_ptr template specified in this subclause has the strict Chris@102: //! ownership semantics, specified above, of a unique pointer. In partial satisfaction of these semantics, each Chris@102: //! such U is MoveConstructible and MoveAssignable, but is not CopyConstructible nor CopyAssignable. Chris@102: //! The template parameter T of unique_ptr may be an incomplete type. Chris@102: //! Chris@102: //! The uses of unique_ptr include providing exception safety for dynamically allocated memory, passing Chris@102: //! ownership of dynamically allocated memory to a function, and returning dynamically allocated memory from Chris@102: //! a function. Chris@102: //! Chris@102: //! If T is an array type (e.g. unique_ptr) the interface is slightly altered: Chris@102: //! - Pointers to types derived from T are rejected by the constructors, and by reset. Chris@102: //! - The observers operator* and operator-> are not provided. Chris@102: //! - The indexing observer operator[] is provided. Chris@102: //! Chris@102: //! \tparam T Provides the type of the stored pointer. Chris@102: //! \tparam D The deleter type: Chris@102: //! - The default type for the template parameter D is default_delete. A client-supplied template argument Chris@102: //! D shall be a function object type, lvalue-reference to function, or lvalue-reference to function object type Chris@102: //! for which, given a value d of type D and a value ptr of type unique_ptr::pointer, the expression Chris@102: //! d(ptr) is valid and has the effect of disposing of the pointer as appropriate for that deleter. Chris@102: //! - If the deleter's type D is not a reference type, D shall satisfy the requirements of Destructible. Chris@102: //! - If the type remove_reference::type::pointer exists, it shall satisfy the requirements of NullablePointer. Chris@102: template > Chris@102: class unique_ptr Chris@102: { Chris@102: #if defined(BOOST_MOVE_DOXYGEN_INVOKED) Chris@102: public: Chris@102: unique_ptr(const unique_ptr&) = delete; Chris@102: unique_ptr& operator=(const unique_ptr&) = delete; Chris@102: private: Chris@102: #else Chris@102: BOOST_MOVABLE_BUT_NOT_COPYABLE(unique_ptr) Chris@102: Chris@102: typedef bmupmu::pointer_type pointer_type_obtainer; Chris@102: typedef bmupd::unique_ptr_data Chris@102: data_type; Chris@102: typedef typename bmupd::deleter_types::deleter_arg_type1 deleter_arg_type1; Chris@102: typedef typename bmupd::deleter_types::deleter_arg_type2 deleter_arg_type2; Chris@102: data_type m_data; Chris@102: #endif Chris@102: Chris@102: public: Chris@102: //! If the type remove_reference::type::pointer exists, then it shall be a Chris@102: //! synonym for remove_reference::type::pointer. Otherwise it shall be a Chris@102: //! synonym for T*. Chris@102: typedef typename BOOST_MOVE_SEEDOC(pointer_type_obtainer::type) pointer; Chris@102: //! If T is an array type, then element_type is equal to T. Otherwise, if T is a type Chris@102: //! in the form U[], element_type is equal to U. Chris@102: typedef typename BOOST_MOVE_SEEDOC(bmupmu::remove_extent::type) element_type; Chris@102: typedef D deleter_type; Chris@102: Chris@102: //! Requires: D shall satisfy the requirements of DefaultConstructible, and Chris@102: //! that construction shall not throw an exception. Chris@102: //! Chris@102: //! Effects: Constructs a unique_ptr object that owns nothing, value-initializing the Chris@102: //! stored pointer and the stored deleter. Chris@102: //! Chris@102: //! Postconditions: get() == nullptr. get_deleter() returns a reference to the stored deleter. Chris@102: //! Chris@102: //! Remarks: If this constructor is instantiated with a pointer type or reference type Chris@102: //! for the template argument D, the program is ill-formed. Chris@102: BOOST_CONSTEXPR unique_ptr() BOOST_NOEXCEPT Chris@102: : m_data() Chris@102: { Chris@102: //If this constructor is instantiated with a pointer type or reference type Chris@102: //for the template argument D, the program is ill-formed. Chris@102: BOOST_STATIC_ASSERT(!bmupmu::is_pointer::value); Chris@102: BOOST_STATIC_ASSERT(!bmupmu::is_reference::value); Chris@102: } Chris@102: Chris@102: //! Effects: Same as unique_ptr() (default constructor). Chris@102: //! Chris@102: BOOST_CONSTEXPR unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT Chris@102: : m_data() Chris@102: { Chris@102: //If this constructor is instantiated with a pointer type or reference type Chris@102: //for the template argument D, the program is ill-formed. Chris@102: BOOST_STATIC_ASSERT(!bmupmu::is_pointer::value); Chris@102: BOOST_STATIC_ASSERT(!bmupmu::is_reference::value); Chris@102: } Chris@102: Chris@102: //! Requires: D shall satisfy the requirements of DefaultConstructible, and Chris@102: //! that construction shall not throw an exception. Chris@102: //! Chris@102: //! Effects: Constructs a unique_ptr which owns p, initializing the stored pointer Chris@102: //! with p and value initializing the stored deleter. Chris@102: //! Chris@102: //! Postconditions: get() == p. get_deleter() returns a reference to the stored deleter. Chris@102: //! Chris@102: //! Remarks: If this constructor is instantiated with a pointer type or reference type Chris@102: //! for the template argument D, the program is ill-formed. Chris@102: //! This constructor shall not participate in overload resolution unless: Chris@102: //! - If T is not an array type and Pointer is implicitly convertible to pointer. Chris@102: //! - If T is an array type and Pointer is a more CV qualified pointer to element_type. Chris@102: template Chris@102: explicit unique_ptr(Pointer p Chris@102: BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr::type* =0) Chris@102: ) BOOST_NOEXCEPT Chris@102: : m_data(p) Chris@102: { Chris@102: //If T is not an array type, element_type_t derives from T Chris@102: //it uses the default deleter and T has no virtual destructor, then you have a problem Chris@102: BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor Chris@102: ::type>::value )); Chris@102: //If this constructor is instantiated with a pointer type or reference type Chris@102: //for the template argument D, the program is ill-formed. Chris@102: BOOST_STATIC_ASSERT(!bmupmu::is_pointer::value); Chris@102: BOOST_STATIC_ASSERT(!bmupmu::is_reference::value); Chris@102: } Chris@102: Chris@102: //!The signature of this constructor depends upon whether D is a reference type. Chris@102: //! - If D is non-reference type A, then the signature is unique_ptr(pointer p, const A& d). Chris@102: //! - If D is an lvalue-reference type A&, then the signature is unique_ptr(pointer p, A& d). Chris@102: //! - If D is an lvalue-reference type const A&, then the signature is unique_ptr(pointer p, const A& d). Chris@102: //! Chris@102: //! Chris@102: //! Requires: Either Chris@102: //! - D is not an lvalue-reference type and d is an lvalue or const rvalue. Chris@102: //! D shall satisfy the requirements of CopyConstructible, and the copy constructor of D Chris@102: //! shall not throw an exception. This unique_ptr will hold a copy of d. Chris@102: //! - D is an lvalue-reference type and d is an lvalue. the type which D references need not be CopyConstructible nor Chris@102: //! MoveConstructible. This unique_ptr will hold a D which refers to the lvalue d. Chris@102: //! Chris@102: //! Effects: Constructs a unique_ptr object which owns p, initializing the stored pointer with p and Chris@102: //! initializing the deleter as described above. Chris@102: //! Chris@102: //! Postconditions: get() == p. get_deleter() returns a reference to the stored deleter. If D is a Chris@102: //! reference type then get_deleter() returns a reference to the lvalue d. Chris@102: //! Chris@102: //! Remarks: This constructor shall not participate in overload resolution unless: Chris@102: //! - If T is not an array type and Pointer is implicitly convertible to pointer. Chris@102: //! - If T is an array type and Pointer is a more CV qualified pointer to element_type. Chris@102: template Chris@102: unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type1) d1 Chris@102: BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr::type* =0) Chris@102: ) BOOST_NOEXCEPT Chris@102: : m_data(p, d1) Chris@102: { Chris@102: //If T is not an array type, element_type_t derives from T Chris@102: //it uses the default deleter and T has no virtual destructor, then you have a problem Chris@102: BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor Chris@102: ::type>::value )); Chris@102: } Chris@102: Chris@102: //! Effects: Same effects as template unique_ptr(Pointer p, deleter_arg_type1 d1) Chris@102: //! and additionally get() == nullptr Chris@102: unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type1) d1) BOOST_NOEXCEPT Chris@102: : m_data(pointer(), d1) Chris@102: {} Chris@102: Chris@102: //! The signature of this constructor depends upon whether D is a reference type. Chris@102: //! - If D is non-reference type A, then the signature is unique_ptr(pointer p, A&& d). Chris@102: //! - If D is an lvalue-reference type A&, then the signature is unique_ptr(pointer p, A&& d). Chris@102: //! - If D is an lvalue-reference type const A&, then the signature is unique_ptr(pointer p, const A&& d). Chris@102: //! Chris@102: //! Requires: Either Chris@102: //! - D is not an lvalue-reference type and d is a non-const rvalue. D Chris@102: //! shall satisfy the requirements of MoveConstructible, and the move constructor Chris@102: //! of D shall not throw an exception. This unique_ptr will hold a value move constructed from d. Chris@102: //! - D is an lvalue-reference type and d is an rvalue, the program is ill-formed. Chris@102: //! Chris@102: //! Effects: Constructs a unique_ptr object which owns p, initializing the stored pointer with p and Chris@102: //! initializing the deleter as described above. Chris@102: //! Chris@102: //! Postconditions: get() == p. get_deleter() returns a reference to the stored deleter. If D is a Chris@102: //! reference type then get_deleter() returns a reference to the lvalue d. Chris@102: //! Chris@102: //! Remarks: This constructor shall not participate in overload resolution unless: Chris@102: //! - If T is not an array type and Pointer is implicitly convertible to pointer. Chris@102: //! - If T is an array type and Pointer is a more CV qualified pointer to element_type. Chris@102: template Chris@102: unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type2) d2 Chris@102: BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr::type* =0) Chris@102: ) BOOST_NOEXCEPT Chris@102: : m_data(p, ::boost::move(d2)) Chris@102: { Chris@102: //If T is not an array type, element_type_t derives from T Chris@102: //it uses the default deleter and T has no virtual destructor, then you have a problem Chris@102: BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor Chris@102: ::type>::value )); Chris@102: } Chris@102: Chris@102: //! Effects: Same effects as template unique_ptr(Pointer p, deleter_arg_type2 d2) Chris@102: //! and additionally get() == nullptr Chris@102: unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type2) d2) BOOST_NOEXCEPT Chris@102: : m_data(pointer(), ::boost::move(d2)) Chris@102: {} Chris@102: Chris@102: //! Requires: If D is not a reference type, D shall satisfy the requirements of MoveConstructible. Chris@102: //! Construction of the deleter from an rvalue of type D shall not throw an exception. Chris@102: //! Chris@102: //! Effects: Constructs a unique_ptr by transferring ownership from u to *this. If D is a reference type, Chris@102: //! this deleter is copy constructed from u's deleter; otherwise, this deleter is move constructed from u's Chris@102: //! deleter. Chris@102: //! Chris@102: //! Postconditions: get() yields the value u.get() yielded before the construction. get_deleter() Chris@102: //! returns a reference to the stored deleter that was constructed from u.get_deleter(). If D is a Chris@102: //! reference type then get_deleter() and u.get_deleter() both reference the same lvalue deleter. Chris@102: unique_ptr(BOOST_RV_REF(unique_ptr) u) BOOST_NOEXCEPT Chris@102: : m_data(u.release(), ::boost::move_if_not_lvalue_reference(u.get_deleter())) Chris@102: {} Chris@102: Chris@102: //! Requires: If E is not a reference type, construction of the deleter from an rvalue of type E shall be Chris@102: //! well formed and shall not throw an exception. Otherwise, E is a reference type and construction of the Chris@102: //! deleter from an lvalue of type E shall be well formed and shall not throw an exception. Chris@102: //! Chris@102: //! Remarks: This constructor shall not participate in overload resolution unless: Chris@102: //! - unique_ptr::pointer is implicitly convertible to pointer, Chris@102: //! - U is not an array type, and Chris@102: //! - either D is a reference type and E is the same type as D, or D is not a reference type and E is Chris@102: //! implicitly convertible to D. Chris@102: //! Chris@102: //! Effects: Constructs a unique_ptr by transferring ownership from u to *this. If E is a reference type, Chris@102: //! this deleter is copy constructed from u's deleter; otherwise, this deleter is move constructed from u's deleter. Chris@102: //! Chris@102: //! Postconditions: get() yields the value u.get() yielded before the construction. get_deleter() Chris@102: //! returns a reference to the stored deleter that was constructed from u.get_deleter(). Chris@102: template Chris@102: unique_ptr( BOOST_RV_REF_BEG unique_ptr BOOST_RV_REF_END u Chris@102: BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_moveconv_constr::type* =0) Chris@102: ) BOOST_NOEXCEPT Chris@102: : m_data(u.release(), ::boost::move_if_not_lvalue_reference(u.get_deleter())) Chris@102: { Chris@102: //If T is not an array type, U derives from T Chris@102: //it uses the default deleter and T has no virtual destructor, then you have a problem Chris@102: BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor Chris@102: ::pointer>::value )); Chris@102: } Chris@102: Chris@102: //! Requires: The expression get_deleter()(get()) shall be well formed, shall have well-defined behavior, Chris@102: //! and shall not throw exceptions. Chris@102: //! Chris@102: //! Effects: If get() == nullpt1r there are no effects. Otherwise get_deleter()(get()). Chris@102: //! Chris@102: //! Note: The use of default_delete requires T to be a complete type Chris@102: ~unique_ptr() Chris@102: { if(m_data.m_p) m_data.deleter()(m_data.m_p); } Chris@102: Chris@102: //! Requires: If D is not a reference type, D shall satisfy the requirements of MoveAssignable Chris@102: //! and assignment of the deleter from an rvalue of type D shall not throw an exception. Otherwise, D Chris@102: //! is a reference type; remove_reference::type shall satisfy the CopyAssignable requirements and Chris@102: //! assignment of the deleter from an lvalue of type D shall not throw an exception. Chris@102: //! Chris@102: //! Effects: Transfers ownership from u to *this as if by calling reset(u.release()) followed Chris@102: //! by get_deleter() = std::forward(u.get_deleter()). Chris@102: //! Chris@102: //! Returns: *this. Chris@102: unique_ptr& operator=(BOOST_RV_REF(unique_ptr) u) BOOST_NOEXCEPT Chris@102: { Chris@102: this->reset(u.release()); Chris@102: m_data.deleter() = ::boost::move_if_not_lvalue_reference(u.get_deleter()); Chris@102: return *this; Chris@102: } Chris@102: Chris@102: //! Requires: If E is not a reference type, assignment of the deleter from an rvalue of type E shall be Chris@102: //! well-formed and shall not throw an exception. Otherwise, E is a reference type and assignment of the Chris@102: //! deleter from an lvalue of type E shall be well-formed and shall not throw an exception. Chris@102: //! Chris@102: //! Remarks: This operator shall not participate in overload resolution unless: Chris@102: //! - unique_ptr::pointer is implicitly convertible to pointer and Chris@102: //! - U is not an array type. Chris@102: //! Chris@102: //! Effects: Transfers ownership from u to *this as if by calling reset(u.release()) followed by Chris@102: //! get_deleter() = std::forward(u.get_deleter()). Chris@102: //! Chris@102: //! Returns: *this. Chris@102: template Chris@102: BOOST_MOVE_DOC1ST(unique_ptr&, typename bmupd::enable_up_moveconv_assign Chris@102: ::type) Chris@102: operator=(BOOST_RV_REF_BEG unique_ptr BOOST_RV_REF_END u) BOOST_NOEXCEPT Chris@102: { Chris@102: this->reset(u.release()); Chris@102: m_data.deleter() = ::boost::move_if_not_lvalue_reference(u.get_deleter()); Chris@102: return *this; Chris@102: } Chris@102: Chris@102: //! Effects: reset(). Chris@102: //! Chris@102: //! Postcondition: get() == nullptr Chris@102: //! Chris@102: //! Returns: *this. Chris@102: unique_ptr& operator=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT Chris@102: { this->reset(); return *this; } Chris@102: Chris@102: //! Requires: get() != nullptr. Chris@102: //! Chris@102: //! Returns: *get(). Chris@102: //! Chris@102: //! Remarks::type) Chris@102: operator*() const BOOST_NOEXCEPT Chris@102: { Chris@102: BOOST_STATIC_ASSERT((!bmupmu::is_array::value)); Chris@102: return *m_data.m_p; Chris@102: } Chris@102: Chris@102: //! Requires: i < the number of elements in the array to which the stored pointer points. Chris@102: //! Chris@102: //! Returns: get()[i]. Chris@102: //! Chris@102: //! Remarks::type) Chris@102: operator[](std::size_t i) const BOOST_NOEXCEPT Chris@102: { Chris@102: BOOST_ASSERT( bmupmu::extent::value == 0 || i < bmupmu::extent::value ); Chris@102: BOOST_ASSERT(m_data.m_p); Chris@102: return m_data.m_p[i]; Chris@102: } Chris@102: Chris@102: //! Requires: get() != nullptr. Chris@102: //! Chris@102: //! Returns: get(). Chris@102: //! Chris@102: //! Note: use typically requires that T be a complete type. Chris@102: //! Chris@102: //! Remarks() const BOOST_NOEXCEPT Chris@102: { Chris@102: BOOST_STATIC_ASSERT((!bmupmu::is_array::value)); Chris@102: BOOST_ASSERT(m_data.m_p); Chris@102: return m_data.m_p; Chris@102: } Chris@102: Chris@102: //! Returns: The stored pointer. Chris@102: //! Chris@102: pointer get() const BOOST_NOEXCEPT Chris@102: { return m_data.m_p; } Chris@102: Chris@102: //! Returns: A reference to the stored deleter. Chris@102: //! Chris@102: BOOST_MOVE_DOC1ST(D&, typename bmupmu::add_lvalue_reference::type) Chris@102: get_deleter() BOOST_NOEXCEPT Chris@102: { return m_data.deleter(); } Chris@102: Chris@102: //! Returns: A reference to the stored deleter. Chris@102: //! Chris@102: BOOST_MOVE_DOC1ST(const D&, typename bmupmu::add_const_lvalue_reference::type) Chris@102: get_deleter() const BOOST_NOEXCEPT Chris@102: { return m_data.deleter(); } Chris@102: Chris@102: #ifdef BOOST_MOVE_DOXYGEN_INVOKED Chris@102: //! Returns: Returns: get() != nullptr. Chris@102: //! Chris@102: explicit operator bool Chris@102: #else Chris@102: operator bmupd::explicit_bool_arg Chris@102: #endif Chris@102: ()const BOOST_NOEXCEPT Chris@102: { Chris@102: return m_data.m_p Chris@102: ? &bmupd::bool_conversion::for_bool Chris@102: : bmupd::explicit_bool_arg(0); Chris@102: } Chris@102: Chris@102: //! Postcondition: get() == nullptr. Chris@102: //! Chris@102: //! Returns: The value get() had at the start of the call to release. Chris@102: pointer release() BOOST_NOEXCEPT Chris@102: { Chris@102: const pointer tmp = m_data.m_p; Chris@102: m_data.m_p = pointer(); Chris@102: return tmp; Chris@102: } Chris@102: Chris@102: //! Requires: The expression get_deleter()(get()) shall be well formed, shall have well-defined behavior, Chris@102: //! and shall not throw exceptions. Chris@102: //! Chris@102: //! Effects: assigns p to the stored pointer, and then if the old value of the stored pointer, old_p, was not Chris@102: //! equal to nullptr, calls get_deleter()(old_p). Note: The order of these operations is significant Chris@102: //! because the call to get_deleter() may destroy *this. Chris@102: //! Chris@102: //! Postconditions: get() == p. Note: The postcondition does not hold if the call to get_deleter() Chris@102: //! destroys *this since this->get() is no longer a valid expression. Chris@102: //! Chris@102: //! Remarks: This constructor shall not participate in overload resolution unless: Chris@102: //! - If T is not an array type and Pointer is implicitly convertible to pointer. Chris@102: //! - If T is an array type and Pointer is a more CV qualified pointer to element_type. Chris@102: template Chris@102: BOOST_MOVE_DOC1ST(void, typename bmupd::enable_up_ptr::type) Chris@102: reset(Pointer p) BOOST_NOEXCEPT Chris@102: { Chris@102: //If T is not an array type, element_type_t derives from T Chris@102: //it uses the default deleter and T has no virtual destructor, then you have a problem Chris@102: BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor Chris@102: ::type>::value )); Chris@102: pointer tmp = m_data.m_p; Chris@102: m_data.m_p = p; Chris@102: if(tmp) m_data.deleter()(tmp); Chris@102: } Chris@102: Chris@102: //! Requires: The expression get_deleter()(get()) shall be well formed, shall have well-defined behavior, Chris@102: //! and shall not throw exceptions. Chris@102: //! Chris@102: //! Effects: assigns nullptr to the stored pointer, and then if the old value of the stored pointer, old_p, was not Chris@102: //! equal to nullptr, calls get_deleter()(old_p). Note: The order of these operations is significant Chris@102: //! because the call to get_deleter() may destroy *this. Chris@102: //! Chris@102: //! Postconditions: get() == p. Note: The postcondition does not hold if the call to get_deleter() Chris@102: //! destroys *this since this->get() is no longer a valid expression. Chris@102: void reset() BOOST_NOEXCEPT Chris@102: { this->reset(pointer()); } Chris@102: Chris@102: //! Effects: Same as reset() Chris@102: //! Chris@102: void reset(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT Chris@102: { this->reset(); } Chris@102: Chris@102: //! Requires: get_deleter() shall be swappable and shall not throw an exception under swap. Chris@102: //! Chris@102: //! Effects: Invokes swap on the stored pointers and on the stored deleters of *this and u. Chris@102: void swap(unique_ptr& u) BOOST_NOEXCEPT Chris@102: { Chris@102: ::boost::adl_move_swap(m_data.m_p, u.m_data.m_p); Chris@102: ::boost::adl_move_swap(m_data.deleter(), u.m_data.deleter()); Chris@102: } Chris@102: }; Chris@102: Chris@102: //! Effects: Calls x.swap(y). Chris@102: //! Chris@102: template Chris@102: inline void swap(unique_ptr &x, unique_ptr &y) BOOST_NOEXCEPT Chris@102: { x.swap(y); } Chris@102: Chris@102: //! Returns: x.get() == y.get(). Chris@102: //! Chris@102: template Chris@102: inline bool operator==(const unique_ptr &x, const unique_ptr &y) Chris@102: { return x.get() == y.get(); } Chris@102: Chris@102: //! Returns: x.get() != y.get(). Chris@102: //! Chris@102: template Chris@102: inline bool operator!=(const unique_ptr &x, const unique_ptr &y) Chris@102: { return x.get() != y.get(); } Chris@102: Chris@102: //! Returns: x.get() < y.get(). Chris@102: //! Chris@102: //! Remarks: This comparison shall induce a Chris@102: //! strict weak ordering betwen pointers. Chris@102: template Chris@102: inline bool operator<(const unique_ptr &x, const unique_ptr &y) Chris@102: { return x.get() < y.get(); } Chris@102: Chris@102: //! Returns: !(y < x). Chris@102: //! Chris@102: template Chris@102: inline bool operator<=(const unique_ptr &x, const unique_ptr &y) Chris@102: { return !(y < x); } Chris@102: Chris@102: //! Returns: y < x. Chris@102: //! Chris@102: template Chris@102: inline bool operator>(const unique_ptr &x, const unique_ptr &y) Chris@102: { return y < x; } Chris@102: Chris@102: //! Returns:!(x < y). Chris@102: //! Chris@102: template Chris@102: inline bool operator>=(const unique_ptr &x, const unique_ptr &y) Chris@102: { return !(x < y); } Chris@102: Chris@102: //! Returns:!x. Chris@102: //! Chris@102: template Chris@102: inline bool operator==(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT Chris@102: { return !x; } Chris@102: Chris@102: //! Returns:!x. Chris@102: //! Chris@102: template Chris@102: inline bool operator==(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr &x) BOOST_NOEXCEPT Chris@102: { return !x; } Chris@102: Chris@102: //! Returns: (bool)x. Chris@102: //! Chris@102: template Chris@102: inline bool operator!=(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT Chris@102: { return !!x; } Chris@102: Chris@102: //! Returns: (bool)x. Chris@102: //! Chris@102: template Chris@102: inline bool operator!=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr &x) BOOST_NOEXCEPT Chris@102: { return !!x; } Chris@102: Chris@102: //! Requires: operator shall induce a strict weak ordering on unique_ptr::pointer values. Chris@102: //! Chris@102: //! Returns: Returns x.get() < pointer(). Chris@102: template Chris@102: inline bool operator<(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) Chris@102: { return x.get() < typename unique_ptr::pointer(); } Chris@102: Chris@102: //! Requires: operator shall induce a strict weak ordering on unique_ptr::pointer values. Chris@102: //! Chris@102: //! Returns: Returns pointer() < x.get(). Chris@102: template Chris@102: inline bool operator<(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr &x) Chris@102: { return typename unique_ptr::pointer() < x.get(); } Chris@102: Chris@102: //! Returns: nullptr < x. Chris@102: //! Chris@102: template Chris@102: inline bool operator>(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) Chris@102: { return x.get() > typename unique_ptr::pointer(); } Chris@102: Chris@102: //! Returns: x < nullptr. Chris@102: //! Chris@102: template Chris@102: inline bool operator>(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr &x) Chris@102: { return typename unique_ptr::pointer() > x.get(); } Chris@102: Chris@102: //! Returns: !(nullptr < x). Chris@102: //! Chris@102: template Chris@102: inline bool operator<=(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) Chris@102: { return !(bmupd::nullptr_type() < x); } Chris@102: Chris@102: //! Returns: !(x < nullptr). Chris@102: //! Chris@102: template Chris@102: inline bool operator<=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr &x) Chris@102: { return !(x < bmupd::nullptr_type()); } Chris@102: Chris@102: //! Returns: !(x < nullptr). Chris@102: //! Chris@102: template Chris@102: inline bool operator>=(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) Chris@102: { return !(x < bmupd::nullptr_type()); } Chris@102: Chris@102: //! Returns: !(nullptr < x). Chris@102: //! Chris@102: template Chris@102: inline bool operator>=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr &x) Chris@102: { return !(bmupd::nullptr_type() < x); } Chris@102: Chris@102: } //namespace movelib { Chris@102: } //namespace boost{ Chris@102: Chris@102: #include Chris@102: Chris@102: #endif //#ifndef BOOST_MOVE_UNIQUE_PTR_HPP_INCLUDED