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