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