unique_ptr.hpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2014-2014. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/move for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. #ifndef BOOST_MOVE_UNIQUE_PTR_HPP_INCLUDED
  11. #define BOOST_MOVE_UNIQUE_PTR_HPP_INCLUDED
  12. #ifndef BOOST_CONFIG_HPP
  13. # include <boost/config.hpp>
  14. #endif
  15. #
  16. #if defined(BOOST_HAS_PRAGMA_ONCE)
  17. # pragma once
  18. #endif
  19. #include <boost/move/detail/config_begin.hpp>
  20. #include <boost/move/detail/workaround.hpp> //forceinline
  21. #include <boost/move/detail/unique_ptr_meta_utils.hpp>
  22. #include <boost/move/default_delete.hpp>
  23. #include <boost/move/utility_core.hpp>
  24. #include <boost/move/adl_move_swap.hpp>
  25. #include <boost/static_assert.hpp>
  26. #include <boost/assert.hpp>
  27. #include <cstddef> //For std::nullptr_t and std::size_t
  28. //!\file
  29. //! Describes the smart pointer unique_ptr, a drop-in replacement for std::unique_ptr,
  30. //! usable also from C++03 compilers.
  31. //!
  32. //! Main differences from std::unique_ptr to avoid heavy dependencies,
  33. //! specially in C++03 compilers:
  34. //! - <tt>operator < </tt> uses pointer <tt>operator < </tt>instead of <tt>std::less<common_type></tt>.
  35. //! This avoids dependencies on <tt>std::common_type</tt> and <tt>std::less</tt>
  36. //! (<tt><type_traits>/<functional></tt> headers). In C++03 this avoid pulling Boost.Typeof and other
  37. //! cascading dependencies. As in all Boost platforms <tt>operator <</tt> on raw pointers and
  38. //! other smart pointers provides strict weak ordering in practice this should not be a problem for users.
  39. //! - assignable from literal 0 for compilers without nullptr
  40. //! - <tt>unique_ptr<T[]></tt> is constructible and assignable from <tt>unique_ptr<U[]></tt> if
  41. //! cv-less T and cv-less U are the same type and T is more CV qualified than U.
  42. namespace boost{
  43. // @cond
  44. namespace move_upd {
  45. ////////////////////////////////////////////
  46. // deleter types
  47. ////////////////////////////////////////////
  48. #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  49. template <class T>
  50. class is_noncopyable
  51. {
  52. typedef char true_t;
  53. class false_t { char dummy[2]; };
  54. template<class U> static false_t dispatch(...);
  55. template<class U> static true_t dispatch(typename U::boost_move_no_copy_constructor_or_assign*);
  56. public:
  57. static const bool value = sizeof(dispatch<T>(0)) == sizeof(true_t);
  58. };
  59. #endif //defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  60. template <class D>
  61. struct deleter_types
  62. {
  63. typedef typename bmupmu::add_lvalue_reference<D>::type del_ref;
  64. typedef typename bmupmu::add_const_lvalue_reference<D>::type del_cref;
  65. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  66. typedef typename bmupmu::if_c
  67. < bmupmu::is_lvalue_reference<D>::value, D, del_cref >::type deleter_arg_type1;
  68. typedef typename bmupmu::remove_reference<D>::type && deleter_arg_type2;
  69. #else
  70. typedef typename bmupmu::if_c
  71. < is_noncopyable<D>::value, bmupmu::nat, del_cref>::type non_ref_deleter_arg1;
  72. typedef typename bmupmu::if_c< bmupmu::is_lvalue_reference<D>::value
  73. , D, non_ref_deleter_arg1 >::type deleter_arg_type1;
  74. typedef ::boost::rv<D> & deleter_arg_type2;
  75. #endif
  76. };
  77. ////////////////////////////////////////////
  78. // unique_ptr_data
  79. ////////////////////////////////////////////
  80. template <class P, class D, bool = bmupmu::is_unary_function<D>::value || bmupmu::is_reference<D>::value >
  81. struct unique_ptr_data
  82. {
  83. typedef typename deleter_types<D>::deleter_arg_type1 deleter_arg_type1;
  84. typedef typename deleter_types<D>::del_ref del_ref;
  85. typedef typename deleter_types<D>::del_cref del_cref;
  86. BOOST_MOVE_FORCEINLINE unique_ptr_data() BOOST_NOEXCEPT
  87. : m_p(), d()
  88. {}
  89. BOOST_MOVE_FORCEINLINE explicit unique_ptr_data(P p) BOOST_NOEXCEPT
  90. : m_p(p), d()
  91. {}
  92. BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT
  93. : m_p(p), d(d1)
  94. {}
  95. template <class U>
  96. BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, BOOST_FWD_REF(U) d1) BOOST_NOEXCEPT
  97. : m_p(p), d(::boost::forward<U>(d1))
  98. {}
  99. BOOST_MOVE_FORCEINLINE del_ref deleter() { return d; }
  100. BOOST_MOVE_FORCEINLINE del_cref deleter() const{ return d; }
  101. P m_p;
  102. D d;
  103. private:
  104. unique_ptr_data& operator=(const unique_ptr_data&);
  105. unique_ptr_data(const unique_ptr_data&);
  106. };
  107. template <class P, class D>
  108. struct unique_ptr_data<P, D, false>
  109. : private D
  110. {
  111. typedef typename deleter_types<D>::deleter_arg_type1 deleter_arg_type1;
  112. typedef typename deleter_types<D>::del_ref del_ref;
  113. typedef typename deleter_types<D>::del_cref del_cref;
  114. BOOST_MOVE_FORCEINLINE unique_ptr_data() BOOST_NOEXCEPT
  115. : D(), m_p()
  116. {}
  117. BOOST_MOVE_FORCEINLINE explicit unique_ptr_data(P p) BOOST_NOEXCEPT
  118. : D(), m_p(p)
  119. {}
  120. BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT
  121. : D(d1), m_p(p)
  122. {}
  123. template <class U>
  124. BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, BOOST_FWD_REF(U) d) BOOST_NOEXCEPT
  125. : D(::boost::forward<U>(d)), m_p(p)
  126. {}
  127. BOOST_MOVE_FORCEINLINE del_ref deleter() BOOST_NOEXCEPT { return static_cast<del_ref>(*this); }
  128. BOOST_MOVE_FORCEINLINE del_cref deleter() const BOOST_NOEXCEPT { return static_cast<del_cref>(*this); }
  129. P m_p;
  130. private:
  131. unique_ptr_data& operator=(const unique_ptr_data&);
  132. unique_ptr_data(const unique_ptr_data&);
  133. };
  134. ////////////////////////////////////////////
  135. // is_unique_ptr_convertible
  136. ////////////////////////////////////////////
  137. //Although non-standard, we avoid using pointer_traits
  138. //to avoid heavy dependencies
  139. template <typename T>
  140. struct get_element_type
  141. {
  142. struct DefaultWrap { typedef bmupmu::natify<T> element_type; };
  143. template <typename X> static char test(int, typename X::element_type*);
  144. template <typename X> static int test(...);
  145. static const bool value = (1 == sizeof(test<T>(0, 0)));
  146. typedef typename bmupmu::if_c<value, T, DefaultWrap>::type::element_type type;
  147. };
  148. template<class T>
  149. struct get_element_type<T*>
  150. {
  151. typedef T type;
  152. };
  153. template<class T>
  154. struct get_cvelement
  155. : bmupmu::remove_cv<typename get_element_type<T>::type>
  156. {};
  157. template <class P1, class P2>
  158. struct is_same_cvelement_and_convertible
  159. {
  160. typedef typename bmupmu::remove_reference<P1>::type arg1;
  161. typedef typename bmupmu::remove_reference<P2>::type arg2;
  162. static const bool same_cvless =
  163. bmupmu::is_same<typename get_cvelement<arg1>::type,typename get_cvelement<arg2>::type>::value;
  164. static const bool value = same_cvless && bmupmu::is_convertible<arg1, arg2>::value;
  165. };
  166. template<bool IsArray, class FromPointer, class ThisPointer>
  167. struct is_unique_ptr_convertible
  168. : is_same_cvelement_and_convertible<FromPointer, ThisPointer>
  169. {};
  170. template<class FromPointer, class ThisPointer>
  171. struct is_unique_ptr_convertible<false, FromPointer, ThisPointer>
  172. : bmupmu::is_convertible<FromPointer, ThisPointer>
  173. {};
  174. ////////////////////////////////////////
  175. //// enable_up_moveconv_assign
  176. ////////////////////////////////////////
  177. template<class T, class FromPointer, class ThisPointer, class Type = bmupmu::nat>
  178. struct enable_up_ptr
  179. : bmupmu::enable_if_c< is_unique_ptr_convertible
  180. < bmupmu::is_array<T>::value, FromPointer, ThisPointer>::value, Type>
  181. {};
  182. ////////////////////////////////////////
  183. //// enable_up_moveconv_assign
  184. ////////////////////////////////////////
  185. template<class T, class D, class U, class E>
  186. struct unique_moveconvert_assignable
  187. {
  188. static const bool t_is_array = bmupmu::is_array<T>::value;
  189. static const bool value =
  190. t_is_array == bmupmu::is_array<U>::value &&
  191. bmupmu::extent<T>::value == bmupmu::extent<U>::value &&
  192. is_unique_ptr_convertible
  193. < t_is_array
  194. , typename bmupmu::pointer_type<U, E>::type, typename bmupmu::pointer_type<T, D>::type
  195. >::value;
  196. };
  197. template<class T, class D, class U, class E, std::size_t N>
  198. struct unique_moveconvert_assignable<T[], D, U[N], E>
  199. : unique_moveconvert_assignable<T[], D, U[], E>
  200. {};
  201. template<class T, class D, class U, class E, class Type = bmupmu::nat>
  202. struct enable_up_moveconv_assign
  203. : bmupmu::enable_if_c<unique_moveconvert_assignable<T, D, U, E>::value, Type>
  204. {};
  205. ////////////////////////////////////////
  206. //// enable_up_moveconv_constr
  207. ////////////////////////////////////////
  208. template<class D, class E, bool IsReference = bmupmu::is_reference<D>::value>
  209. struct unique_deleter_is_initializable
  210. : bmupmu::is_same<D, E>
  211. {};
  212. template <class T, class U>
  213. class is_rvalue_convertible
  214. {
  215. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  216. typedef typename bmupmu::remove_reference<T>::type&& t_from;
  217. #else
  218. typedef typename bmupmu::if_c
  219. < ::boost::has_move_emulation_enabled<T>::value && !bmupmu::is_reference<T>::value
  220. , ::boost::rv<T>&
  221. , typename bmupmu::add_lvalue_reference<T>::type
  222. >::type t_from;
  223. #endif
  224. typedef char true_t;
  225. class false_t { char dummy[2]; };
  226. static false_t dispatch(...);
  227. static true_t dispatch(U);
  228. static t_from trigger();
  229. public:
  230. static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t);
  231. };
  232. template<class D, class E>
  233. struct unique_deleter_is_initializable<D, E, false>
  234. {
  235. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  236. //Clang has some problems with is_rvalue_convertible with non-copyable types
  237. //so use intrinsic if available
  238. #if defined(BOOST_CLANG)
  239. #if __has_feature(is_convertible_to)
  240. static const bool value = __is_convertible_to(E, D);
  241. #else
  242. static const bool value = is_rvalue_convertible<E, D>::value;
  243. #endif
  244. #else
  245. static const bool value = is_rvalue_convertible<E, D>::value;
  246. #endif
  247. #else //!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  248. //No hope for compilers with move emulation for now. In several compilers is_convertible
  249. // leads to errors, so just move the Deleter and see if the conversion works
  250. static const bool value = true; /*is_rvalue_convertible<E, D>::value*/
  251. #endif
  252. };
  253. template<class T, class D, class U, class E, class Type = bmupmu::nat>
  254. struct enable_up_moveconv_constr
  255. : bmupmu::enable_if_c
  256. < unique_moveconvert_assignable<T, D, U, E>::value && unique_deleter_is_initializable<D, E>::value
  257. , Type>
  258. {};
  259. } //namespace move_upd {
  260. // @endcond
  261. namespace movelib {
  262. //! A unique pointer is an object that owns another object and
  263. //! manages that other object through a pointer.
  264. //!
  265. //! More precisely, a unique pointer is an object u that stores a pointer to a second object p and will dispose
  266. //! of p when u is itself destroyed (e.g., when leaving block scope). In this context, u is said to own p.
  267. //!
  268. //! The mechanism by which u disposes of p is known as p's associated deleter, a function object whose correct
  269. //! invocation results in p's appropriate disposition (typically its deletion).
  270. //!
  271. //! Let the notation u.p denote the pointer stored by u, and let u.d denote the associated deleter. Upon request,
  272. //! u can reset (replace) u.p and u.d with another pointer and deleter, but must properly dispose of its owned
  273. //! object via the associated deleter before such replacement is considered completed.
  274. //!
  275. //! Additionally, u can, upon request, transfer ownership to another unique pointer u2. Upon completion of
  276. //! such a transfer, the following postconditions hold:
  277. //! - u2.p is equal to the pre-transfer u.p,
  278. //! - u.p is equal to nullptr, and
  279. //! - if the pre-transfer u.d maintained state, such state has been transferred to u2.d.
  280. //!
  281. //! As in the case of a reset, u2 must properly dispose of its pre-transfer owned object via the pre-transfer
  282. //! associated deleter before the ownership transfer is considered complete.
  283. //!
  284. //! Each object of a type U instantiated from the unique_ptr template specified in this subclause has the strict
  285. //! ownership semantics, specified above, of a unique pointer. In partial satisfaction of these semantics, each
  286. //! such U is MoveConstructible and MoveAssignable, but is not CopyConstructible nor CopyAssignable.
  287. //! The template parameter T of unique_ptr may be an incomplete type.
  288. //!
  289. //! The uses of unique_ptr include providing exception safety for dynamically allocated memory, passing
  290. //! ownership of dynamically allocated memory to a function, and returning dynamically allocated memory from
  291. //! a function.
  292. //!
  293. //! If T is an array type (e.g. unique_ptr<MyType[]>) the interface is slightly altered:
  294. //! - Pointers to types derived from T are rejected by the constructors, and by reset.
  295. //! - The observers <tt>operator*</tt> and <tt>operator-></tt> are not provided.
  296. //! - The indexing observer <tt>operator[]</tt> is provided.
  297. //!
  298. //! \tparam T Provides the type of the stored pointer.
  299. //! \tparam D The deleter type:
  300. //! - The default type for the template parameter D is default_delete. A client-supplied template argument
  301. //! D shall be a function object type, lvalue-reference to function, or lvalue-reference to function object type
  302. //! for which, given a value d of type D and a value ptr of type unique_ptr<T, D>::pointer, the expression
  303. //! d(ptr) is valid and has the effect of disposing of the pointer as appropriate for that deleter.
  304. //! - If the deleter's type D is not a reference type, D shall satisfy the requirements of Destructible.
  305. //! - If the type <tt>remove_reference<D>::type::pointer</tt> exists, it shall satisfy the requirements of NullablePointer.
  306. template <class T, class D = default_delete<T> >
  307. class unique_ptr
  308. {
  309. #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
  310. public:
  311. unique_ptr(const unique_ptr&) = delete;
  312. unique_ptr& operator=(const unique_ptr&) = delete;
  313. private:
  314. #else
  315. BOOST_MOVABLE_BUT_NOT_COPYABLE(unique_ptr)
  316. typedef bmupmu::pointer_type<T, D > pointer_type_obtainer;
  317. typedef bmupd::unique_ptr_data
  318. <typename pointer_type_obtainer::type, D> data_type;
  319. typedef typename bmupd::deleter_types<D>::deleter_arg_type1 deleter_arg_type1;
  320. typedef typename bmupd::deleter_types<D>::deleter_arg_type2 deleter_arg_type2;
  321. data_type m_data;
  322. #endif
  323. public:
  324. //! If the type <tt>remove_reference<D>::type::pointer</tt> exists, then it shall be a
  325. //! synonym for <tt>remove_reference<D>::type::pointer</tt>. Otherwise it shall be a
  326. //! synonym for T*.
  327. typedef typename BOOST_MOVE_SEEDOC(pointer_type_obtainer::type) pointer;
  328. //! If T is an array type, then element_type is equal to T. Otherwise, if T is a type
  329. //! in the form U[], element_type is equal to U.
  330. typedef typename BOOST_MOVE_SEEDOC(bmupmu::remove_extent<T>::type) element_type;
  331. typedef D deleter_type;
  332. //! <b>Requires</b>: D shall satisfy the requirements of DefaultConstructible, and
  333. //! that construction shall not throw an exception.
  334. //!
  335. //! <b>Effects</b>: Constructs a unique_ptr object that owns nothing, value-initializing the
  336. //! stored pointer and the stored deleter.
  337. //!
  338. //! <b>Postconditions</b>: <tt>get() == nullptr</tt>. <tt>get_deleter()</tt> returns a reference to the stored deleter.
  339. //!
  340. //! <b>Remarks</b>: If this constructor is instantiated with a pointer type or reference type
  341. //! for the template argument D, the program is ill-formed.
  342. BOOST_MOVE_FORCEINLINE BOOST_CONSTEXPR unique_ptr() BOOST_NOEXCEPT
  343. : m_data()
  344. {
  345. //If this constructor is instantiated with a pointer type or reference type
  346. //for the template argument D, the program is ill-formed.
  347. BOOST_STATIC_ASSERT(!bmupmu::is_pointer<D>::value);
  348. BOOST_STATIC_ASSERT(!bmupmu::is_reference<D>::value);
  349. }
  350. //! <b>Effects</b>: Same as <tt>unique_ptr()</tt> (default constructor).
  351. //!
  352. BOOST_MOVE_FORCEINLINE BOOST_CONSTEXPR unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
  353. : m_data()
  354. {
  355. //If this constructor is instantiated with a pointer type or reference type
  356. //for the template argument D, the program is ill-formed.
  357. BOOST_STATIC_ASSERT(!bmupmu::is_pointer<D>::value);
  358. BOOST_STATIC_ASSERT(!bmupmu::is_reference<D>::value);
  359. }
  360. //! <b>Requires</b>: D shall satisfy the requirements of DefaultConstructible, and
  361. //! that construction shall not throw an exception.
  362. //!
  363. //! <b>Effects</b>: Constructs a unique_ptr which owns p, initializing the stored pointer
  364. //! with p and value initializing the stored deleter.
  365. //!
  366. //! <b>Postconditions</b>: <tt>get() == p</tt>. <tt>get_deleter()</tt> returns a reference to the stored deleter.
  367. //!
  368. //! <b>Remarks</b>: If this constructor is instantiated with a pointer type or reference type
  369. //! for the template argument D, the program is ill-formed.
  370. //! This constructor shall not participate in overload resolution unless:
  371. //! - If T is not an array type and Pointer is implicitly convertible to pointer.
  372. //! - If T is an array type and Pointer is a more CV qualified pointer to element_type.
  373. template<class Pointer>
  374. BOOST_MOVE_FORCEINLINE explicit unique_ptr(Pointer p
  375. BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer>::type* =0)
  376. ) BOOST_NOEXCEPT
  377. : m_data(p)
  378. {
  379. //If T is not an array type, element_type_t<Pointer> derives from T
  380. //it uses the default deleter and T has no virtual destructor, then you have a problem
  381. BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
  382. <D, typename bmupd::get_element_type<Pointer>::type>::value ));
  383. //If this constructor is instantiated with a pointer type or reference type
  384. //for the template argument D, the program is ill-formed.
  385. BOOST_STATIC_ASSERT(!bmupmu::is_pointer<D>::value);
  386. BOOST_STATIC_ASSERT(!bmupmu::is_reference<D>::value);
  387. }
  388. //!The signature of this constructor depends upon whether D is a reference type.
  389. //! - If D is non-reference type A, then the signature is <tt>unique_ptr(pointer p, const A& d)</tt>.
  390. //! - If D is an lvalue-reference type A&, then the signature is <tt>unique_ptr(pointer p, A& d)</tt>.
  391. //! - If D is an lvalue-reference type const A&, then the signature is <tt>unique_ptr(pointer p, const A& d)</tt>.
  392. //!
  393. //!
  394. //! <b>Requires</b>: Either
  395. //! - D is not an lvalue-reference type and d is an lvalue or const rvalue.
  396. //! D shall satisfy the requirements of CopyConstructible, and the copy constructor of D
  397. //! shall not throw an exception. This unique_ptr will hold a copy of d.
  398. //! - D is an lvalue-reference type and d is an lvalue. the type which D references need not be CopyConstructible nor
  399. //! MoveConstructible. This unique_ptr will hold a D which refers to the lvalue d.
  400. //!
  401. //! <b>Effects</b>: Constructs a unique_ptr object which owns p, initializing the stored pointer with p and
  402. //! initializing the deleter as described above.
  403. //!
  404. //! <b>Postconditions</b>: <tt>get() == p</tt>. <tt>get_deleter()</tt> returns a reference to the stored deleter. If D is a
  405. //! reference type then <tt>get_deleter()</tt> returns a reference to the lvalue d.
  406. //!
  407. //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless:
  408. //! - If T is not an array type and Pointer is implicitly convertible to pointer.
  409. //! - If T is an array type and Pointer is a more CV qualified pointer to element_type.
  410. template<class Pointer>
  411. BOOST_MOVE_FORCEINLINE unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type1) d1
  412. BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer>::type* =0)
  413. ) BOOST_NOEXCEPT
  414. : m_data(p, d1)
  415. {
  416. //If T is not an array type, element_type_t<Pointer> derives from T
  417. //it uses the default deleter and T has no virtual destructor, then you have a problem
  418. BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
  419. <D, typename bmupd::get_element_type<Pointer>::type>::value ));
  420. }
  421. //! <b>Effects</b>: Same effects as <tt>template<class Pointer> unique_ptr(Pointer p, deleter_arg_type1 d1)</tt>
  422. //! and additionally <tt>get() == nullptr</tt>
  423. BOOST_MOVE_FORCEINLINE unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type1) d1) BOOST_NOEXCEPT
  424. : m_data(pointer(), d1)
  425. {}
  426. //! The signature of this constructor depends upon whether D is a reference type.
  427. //! - If D is non-reference type A, then the signature is <tt>unique_ptr(pointer p, A&& d)</tt>.
  428. //! - If D is an lvalue-reference type A&, then the signature is <tt>unique_ptr(pointer p, A&& d)</tt>.
  429. //! - If D is an lvalue-reference type const A&, then the signature is <tt>unique_ptr(pointer p, const A&& d)</tt>.
  430. //!
  431. //! <b>Requires</b>: Either
  432. //! - D is not an lvalue-reference type and d is a non-const rvalue. D
  433. //! shall satisfy the requirements of MoveConstructible, and the move constructor
  434. //! of D shall not throw an exception. This unique_ptr will hold a value move constructed from d.
  435. //! - D is an lvalue-reference type and d is an rvalue, the program is ill-formed.
  436. //!
  437. //! <b>Effects</b>: Constructs a unique_ptr object which owns p, initializing the stored pointer with p and
  438. //! initializing the deleter as described above.
  439. //!
  440. //! <b>Postconditions</b>: <tt>get() == p</tt>. <tt>get_deleter()</tt> returns a reference to the stored deleter. If D is a
  441. //! reference type then <tt>get_deleter()</tt> returns a reference to the lvalue d.
  442. //!
  443. //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless:
  444. //! - If T is not an array type and Pointer is implicitly convertible to pointer.
  445. //! - If T is an array type and Pointer is a more CV qualified pointer to element_type.
  446. template<class Pointer>
  447. BOOST_MOVE_FORCEINLINE unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type2) d2
  448. BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer>::type* =0)
  449. ) BOOST_NOEXCEPT
  450. : m_data(p, ::boost::move(d2))
  451. {
  452. //If T is not an array type, element_type_t<Pointer> derives from T
  453. //it uses the default deleter and T has no virtual destructor, then you have a problem
  454. BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
  455. <D, typename bmupd::get_element_type<Pointer>::type>::value ));
  456. }
  457. //! <b>Effects</b>: Same effects as <tt>template<class Pointer> unique_ptr(Pointer p, deleter_arg_type2 d2)</tt>
  458. //! and additionally <tt>get() == nullptr</tt>
  459. BOOST_MOVE_FORCEINLINE unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type2) d2) BOOST_NOEXCEPT
  460. : m_data(pointer(), ::boost::move(d2))
  461. {}
  462. //! <b>Requires</b>: If D is not a reference type, D shall satisfy the requirements of MoveConstructible.
  463. //! Construction of the deleter from an rvalue of type D shall not throw an exception.
  464. //!
  465. //! <b>Effects</b>: Constructs a unique_ptr by transferring ownership from u to *this. If D is a reference type,
  466. //! this deleter is copy constructed from u's deleter; otherwise, this deleter is move constructed from u's
  467. //! deleter.
  468. //!
  469. //! <b>Postconditions</b>: <tt>get()</tt> yields the value u.get() yielded before the construction. <tt>get_deleter()</tt>
  470. //! returns a reference to the stored deleter that was constructed from u.get_deleter(). If D is a
  471. //! reference type then <tt>get_deleter()</tt> and <tt>u.get_deleter()</tt> both reference the same lvalue deleter.
  472. BOOST_MOVE_FORCEINLINE unique_ptr(BOOST_RV_REF(unique_ptr) u) BOOST_NOEXCEPT
  473. : m_data(u.release(), ::boost::move_if_not_lvalue_reference<D>(u.get_deleter()))
  474. {}
  475. //! <b>Requires</b>: If E is not a reference type, construction of the deleter from an rvalue of type E shall be
  476. //! well formed and shall not throw an exception. Otherwise, E is a reference type and construction of the
  477. //! deleter from an lvalue of type E shall be well formed and shall not throw an exception.
  478. //!
  479. //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless:
  480. //! - <tt>unique_ptr<U, E>::pointer</tt> is implicitly convertible to pointer,
  481. //! - U is not an array type, and
  482. //! - either D is a reference type and E is the same type as D, or D is not a reference type and E is
  483. //! implicitly convertible to D.
  484. //!
  485. //! <b>Effects</b>: Constructs a unique_ptr by transferring ownership from u to *this. If E is a reference type,
  486. //! this deleter is copy constructed from u's deleter; otherwise, this deleter is move constructed from u's deleter.
  487. //!
  488. //! <b>Postconditions</b>: <tt>get()</tt> yields the value <tt>u.get()</tt> yielded before the construction. <tt>get_deleter()</tt>
  489. //! returns a reference to the stored deleter that was constructed from <tt>u.get_deleter()</tt>.
  490. template <class U, class E>
  491. BOOST_MOVE_FORCEINLINE unique_ptr( BOOST_RV_REF_BEG_IF_CXX11 unique_ptr<U, E> BOOST_RV_REF_END_IF_CXX11 u
  492. BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_moveconv_constr<T BOOST_MOVE_I D BOOST_MOVE_I U BOOST_MOVE_I E>::type* =0)
  493. ) BOOST_NOEXCEPT
  494. : m_data(u.release(), ::boost::move_if_not_lvalue_reference<E>(u.get_deleter()))
  495. {
  496. //If T is not an array type, U derives from T
  497. //it uses the default deleter and T has no virtual destructor, then you have a problem
  498. BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
  499. <D, typename unique_ptr<U, E>::pointer>::value ));
  500. }
  501. //! <b>Requires</b>: The expression <tt>get_deleter()(get())</tt> shall be well formed, shall have well-defined behavior,
  502. //! and shall not throw exceptions.
  503. //!
  504. //! <b>Effects</b>: If <tt>get() == nullpt1r</tt> there are no effects. Otherwise <tt>get_deleter()(get())</tt>.
  505. //!
  506. //! <b>Note</b>: The use of default_delete requires T to be a complete type
  507. ~unique_ptr()
  508. { if(m_data.m_p) m_data.deleter()(m_data.m_p); }
  509. //! <b>Requires</b>: If D is not a reference type, D shall satisfy the requirements of MoveAssignable
  510. //! and assignment of the deleter from an rvalue of type D shall not throw an exception. Otherwise, D
  511. //! is a reference type; <tt>remove_reference<D>::type</tt> shall satisfy the CopyAssignable requirements and
  512. //! assignment of the deleter from an lvalue of type D shall not throw an exception.
  513. //!
  514. //! <b>Effects</b>: Transfers ownership from u to *this as if by calling <tt>reset(u.release())</tt> followed
  515. //! by <tt>get_deleter() = std::forward<D>(u.get_deleter())</tt>.
  516. //!
  517. //! <b>Returns</b>: *this.
  518. unique_ptr& operator=(BOOST_RV_REF(unique_ptr) u) BOOST_NOEXCEPT
  519. {
  520. this->reset(u.release());
  521. m_data.deleter() = ::boost::move_if_not_lvalue_reference<D>(u.get_deleter());
  522. return *this;
  523. }
  524. //! <b>Requires</b>: If E is not a reference type, assignment of the deleter from an rvalue of type E shall be
  525. //! well-formed and shall not throw an exception. Otherwise, E is a reference type and assignment of the
  526. //! deleter from an lvalue of type E shall be well-formed and shall not throw an exception.
  527. //!
  528. //! <b>Remarks</b>: This operator shall not participate in overload resolution unless:
  529. //! - <tt>unique_ptr<U, E>::pointer</tt> is implicitly convertible to pointer and
  530. //! - U is not an array type.
  531. //!
  532. //! <b>Effects</b>: Transfers ownership from u to *this as if by calling <tt>reset(u.release())</tt> followed by
  533. //! <tt>get_deleter() = std::forward<E>(u.get_deleter())</tt>.
  534. //!
  535. //! <b>Returns</b>: *this.
  536. template <class U, class E>
  537. BOOST_MOVE_DOC1ST(unique_ptr&, typename bmupd::enable_up_moveconv_assign
  538. <T BOOST_MOVE_I D BOOST_MOVE_I U BOOST_MOVE_I E BOOST_MOVE_I unique_ptr &>::type)
  539. operator=(BOOST_RV_REF_BEG unique_ptr<U, E> BOOST_RV_REF_END u) BOOST_NOEXCEPT
  540. {
  541. this->reset(u.release());
  542. m_data.deleter() = ::boost::move_if_not_lvalue_reference<E>(u.get_deleter());
  543. return *this;
  544. }
  545. //! <b>Effects</b>: <tt>reset()</tt>.
  546. //!
  547. //! <b>Postcondition</b>: <tt>get() == nullptr</tt>
  548. //!
  549. //! <b>Returns</b>: *this.
  550. unique_ptr& operator=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
  551. { this->reset(); return *this; }
  552. //! <b>Requires</b>: <tt>get() != nullptr</tt>.
  553. //!
  554. //! <b>Returns</b>: <tt>*get()</tt>.
  555. //!
  556. //! <b>Remarks</b: If T is an array type, the program is ill-formed.
  557. BOOST_MOVE_DOC1ST(element_type&, typename bmupmu::add_lvalue_reference<element_type>::type)
  558. operator*() const BOOST_NOEXCEPT
  559. {
  560. BOOST_STATIC_ASSERT((!bmupmu::is_array<T>::value));
  561. return *m_data.m_p;
  562. }
  563. //! <b>Requires</b>: i < the number of elements in the array to which the stored pointer points.
  564. //!
  565. //! <b>Returns</b>: <tt>get()[i]</tt>.
  566. //!
  567. //! <b>Remarks</b: If T is not an array type, the program is ill-formed.
  568. BOOST_MOVE_FORCEINLINE BOOST_MOVE_DOC1ST(element_type&, typename bmupmu::add_lvalue_reference<element_type>::type)
  569. operator[](std::size_t i) const BOOST_NOEXCEPT
  570. {
  571. BOOST_ASSERT( bmupmu::extent<T>::value == 0 || i < bmupmu::extent<T>::value );
  572. BOOST_ASSERT(m_data.m_p);
  573. return m_data.m_p[i];
  574. }
  575. //! <b>Requires</b>: <tt>get() != nullptr</tt>.
  576. //!
  577. //! <b>Returns</b>: <tt>get()</tt>.
  578. //!
  579. //! <b>Note</b>: use typically requires that T be a complete type.
  580. //!
  581. //! <b>Remarks</b: If T is an array type, the program is ill-formed.
  582. BOOST_MOVE_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT
  583. {
  584. BOOST_STATIC_ASSERT((!bmupmu::is_array<T>::value));
  585. BOOST_ASSERT(m_data.m_p);
  586. return m_data.m_p;
  587. }
  588. //! <b>Returns</b>: The stored pointer.
  589. //!
  590. BOOST_MOVE_FORCEINLINE pointer get() const BOOST_NOEXCEPT
  591. { return m_data.m_p; }
  592. //! <b>Returns</b>: A reference to the stored deleter.
  593. //!
  594. BOOST_MOVE_FORCEINLINE BOOST_MOVE_DOC1ST(D&, typename bmupmu::add_lvalue_reference<D>::type)
  595. get_deleter() BOOST_NOEXCEPT
  596. { return m_data.deleter(); }
  597. //! <b>Returns</b>: A reference to the stored deleter.
  598. //!
  599. BOOST_MOVE_FORCEINLINE BOOST_MOVE_DOC1ST(const D&, typename bmupmu::add_const_lvalue_reference<D>::type)
  600. get_deleter() const BOOST_NOEXCEPT
  601. { return m_data.deleter(); }
  602. #ifdef BOOST_MOVE_DOXYGEN_INVOKED
  603. //! <b>Returns</b>: Returns: get() != nullptr.
  604. //!
  605. BOOST_MOVE_FORCEINLINE explicit operator bool
  606. #else
  607. BOOST_MOVE_FORCEINLINE operator bmupd::explicit_bool_arg
  608. #endif
  609. ()const BOOST_NOEXCEPT
  610. {
  611. return m_data.m_p
  612. ? &bmupd::bool_conversion::for_bool
  613. : bmupd::explicit_bool_arg(0);
  614. }
  615. //! <b>Postcondition</b>: <tt>get() == nullptr</tt>.
  616. //!
  617. //! <b>Returns</b>: The value <tt>get()</tt> had at the start of the call to release.
  618. BOOST_MOVE_FORCEINLINE pointer release() BOOST_NOEXCEPT
  619. {
  620. const pointer tmp = m_data.m_p;
  621. m_data.m_p = pointer();
  622. return tmp;
  623. }
  624. //! <b>Requires</b>: The expression <tt>get_deleter()(get())</tt> shall be well formed, shall have well-defined behavior,
  625. //! and shall not throw exceptions.
  626. //!
  627. //! <b>Effects</b>: assigns p to the stored pointer, and then if the old value of the stored pointer, old_p, was not
  628. //! equal to nullptr, calls <tt>get_deleter()(old_p)</tt>. Note: The order of these operations is significant
  629. //! because the call to <tt>get_deleter()</tt> may destroy *this.
  630. //!
  631. //! <b>Postconditions</b>: <tt>get() == p</tt>. Note: The postcondition does not hold if the call to <tt>get_deleter()</tt>
  632. //! destroys *this since <tt>this->get()</tt> is no longer a valid expression.
  633. //!
  634. //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless:
  635. //! - If T is not an array type and Pointer is implicitly convertible to pointer.
  636. //! - If T is an array type and Pointer is a more CV qualified pointer to element_type.
  637. template<class Pointer>
  638. BOOST_MOVE_DOC1ST(void, typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer BOOST_MOVE_I void>::type)
  639. reset(Pointer p) BOOST_NOEXCEPT
  640. {
  641. //If T is not an array type, element_type_t<Pointer> derives from T
  642. //it uses the default deleter and T has no virtual destructor, then you have a problem
  643. BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
  644. <D, typename bmupd::get_element_type<Pointer>::type>::value ));
  645. pointer tmp = m_data.m_p;
  646. m_data.m_p = p;
  647. if(tmp) m_data.deleter()(tmp);
  648. }
  649. //! <b>Requires</b>: The expression <tt>get_deleter()(get())</tt> shall be well formed, shall have well-defined behavior,
  650. //! and shall not throw exceptions.
  651. //!
  652. //! <b>Effects</b>: assigns nullptr to the stored pointer, and then if the old value of the stored pointer, old_p, was not
  653. //! equal to nullptr, calls <tt>get_deleter()(old_p)</tt>. Note: The order of these operations is significant
  654. //! because the call to <tt>get_deleter()</tt> may destroy *this.
  655. //!
  656. //! <b>Postconditions</b>: <tt>get() == p</tt>. Note: The postcondition does not hold if the call to <tt>get_deleter()</tt>
  657. //! destroys *this since <tt>this->get()</tt> is no longer a valid expression.
  658. void reset() BOOST_NOEXCEPT
  659. { this->reset(pointer()); }
  660. //! <b>Effects</b>: Same as <tt>reset()</tt>
  661. //!
  662. void reset(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
  663. { this->reset(); }
  664. //! <b>Requires</b>: <tt>get_deleter()</tt> shall be swappable and shall not throw an exception under swap.
  665. //!
  666. //! <b>Effects</b>: Invokes swap on the stored pointers and on the stored deleters of *this and u.
  667. void swap(unique_ptr& u) BOOST_NOEXCEPT
  668. {
  669. ::boost::adl_move_swap(m_data.m_p, u.m_data.m_p);
  670. ::boost::adl_move_swap(m_data.deleter(), u.m_data.deleter());
  671. }
  672. };
  673. //! <b>Effects</b>: Calls <tt>x.swap(y)</tt>.
  674. //!
  675. template <class T, class D>
  676. BOOST_MOVE_FORCEINLINE void swap(unique_ptr<T, D> &x, unique_ptr<T, D> &y) BOOST_NOEXCEPT
  677. { x.swap(y); }
  678. //! <b>Returns</b>: <tt>x.get() == y.get()</tt>.
  679. //!
  680. template <class T1, class D1, class T2, class D2>
  681. BOOST_MOVE_FORCEINLINE bool operator==(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
  682. { return x.get() == y.get(); }
  683. //! <b>Returns</b>: <tt>x.get() != y.get()</tt>.
  684. //!
  685. template <class T1, class D1, class T2, class D2>
  686. BOOST_MOVE_FORCEINLINE bool operator!=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
  687. { return x.get() != y.get(); }
  688. //! <b>Returns</b>: x.get() < y.get().
  689. //!
  690. //! <b>Remarks</b>: This comparison shall induce a
  691. //! strict weak ordering betwen pointers.
  692. template <class T1, class D1, class T2, class D2>
  693. BOOST_MOVE_FORCEINLINE bool operator<(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
  694. { return x.get() < y.get(); }
  695. //! <b>Returns</b>: !(y < x).
  696. //!
  697. template <class T1, class D1, class T2, class D2>
  698. BOOST_MOVE_FORCEINLINE bool operator<=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
  699. { return !(y < x); }
  700. //! <b>Returns</b>: y < x.
  701. //!
  702. template <class T1, class D1, class T2, class D2>
  703. BOOST_MOVE_FORCEINLINE bool operator>(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
  704. { return y < x; }
  705. //! <b>Returns</b>:!(x < y).
  706. //!
  707. template <class T1, class D1, class T2, class D2>
  708. BOOST_MOVE_FORCEINLINE bool operator>=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
  709. { return !(x < y); }
  710. //! <b>Returns</b>:!x.
  711. //!
  712. template <class T, class D>
  713. BOOST_MOVE_FORCEINLINE bool operator==(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
  714. { return !x; }
  715. //! <b>Returns</b>:!x.
  716. //!
  717. template <class T, class D>
  718. BOOST_MOVE_FORCEINLINE bool operator==(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x) BOOST_NOEXCEPT
  719. { return !x; }
  720. //! <b>Returns</b>: (bool)x.
  721. //!
  722. template <class T, class D>
  723. BOOST_MOVE_FORCEINLINE bool operator!=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
  724. { return !!x; }
  725. //! <b>Returns</b>: (bool)x.
  726. //!
  727. template <class T, class D>
  728. BOOST_MOVE_FORCEINLINE bool operator!=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x) BOOST_NOEXCEPT
  729. { return !!x; }
  730. //! <b>Requires</b>: <tt>operator </tt> shall induce a strict weak ordering on unique_ptr<T, D>::pointer values.
  731. //!
  732. //! <b>Returns</b>: Returns <tt>x.get() < pointer()</tt>.
  733. template <class T, class D>
  734. BOOST_MOVE_FORCEINLINE bool operator<(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
  735. { return x.get() < typename unique_ptr<T, D>::pointer(); }
  736. //! <b>Requires</b>: <tt>operator </tt> shall induce a strict weak ordering on unique_ptr<T, D>::pointer values.
  737. //!
  738. //! <b>Returns</b>: Returns <tt>pointer() < x.get()</tt>.
  739. template <class T, class D>
  740. BOOST_MOVE_FORCEINLINE bool operator<(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
  741. { return typename unique_ptr<T, D>::pointer() < x.get(); }
  742. //! <b>Returns</b>: <tt>nullptr < x</tt>.
  743. //!
  744. template <class T, class D>
  745. BOOST_MOVE_FORCEINLINE bool operator>(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
  746. { return x.get() > typename unique_ptr<T, D>::pointer(); }
  747. //! <b>Returns</b>: <tt>x < nullptr</tt>.
  748. //!
  749. template <class T, class D>
  750. BOOST_MOVE_FORCEINLINE bool operator>(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
  751. { return typename unique_ptr<T, D>::pointer() > x.get(); }
  752. //! <b>Returns</b>: <tt>!(nullptr < x)</tt>.
  753. //!
  754. template <class T, class D>
  755. BOOST_MOVE_FORCEINLINE bool operator<=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
  756. { return !(bmupd::nullptr_type() < x); }
  757. //! <b>Returns</b>: <tt>!(x < nullptr)</tt>.
  758. //!
  759. template <class T, class D>
  760. BOOST_MOVE_FORCEINLINE bool operator<=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
  761. { return !(x < bmupd::nullptr_type()); }
  762. //! <b>Returns</b>: <tt>!(x < nullptr)</tt>.
  763. //!
  764. template <class T, class D>
  765. BOOST_MOVE_FORCEINLINE bool operator>=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
  766. { return !(x < bmupd::nullptr_type()); }
  767. //! <b>Returns</b>: <tt>!(nullptr < x)</tt>.
  768. //!
  769. template <class T, class D>
  770. BOOST_MOVE_FORCEINLINE bool operator>=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
  771. { return !(bmupd::nullptr_type() < x); }
  772. } //namespace movelib {
  773. } //namespace boost{
  774. #include <boost/move/detail/config_end.hpp>
  775. #endif //#ifndef BOOST_MOVE_UNIQUE_PTR_HPP_INCLUDED