Line data Source code
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> //forceinline
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 boost{
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 ::boost::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 :
96 : BOOST_MOVE_FORCEINLINE unique_ptr_data() BOOST_NOEXCEPT
97 : : m_p(), d()
98 : {}
99 :
100 : BOOST_MOVE_FORCEINLINE explicit unique_ptr_data(P p) BOOST_NOEXCEPT
101 : : m_p(p), d()
102 : {}
103 :
104 : BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT
105 : : m_p(p), d(d1)
106 : {}
107 :
108 : template <class U>
109 : BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, BOOST_FWD_REF(U) d1) BOOST_NOEXCEPT
110 : : m_p(p), d(::boost::forward<U>(d1))
111 : {}
112 :
113 : BOOST_MOVE_FORCEINLINE del_ref deleter() { return d; }
114 : BOOST_MOVE_FORCEINLINE 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 :
132 : BOOST_MOVE_FORCEINLINE unique_ptr_data() BOOST_NOEXCEPT
133 : : D(), m_p()
134 : {}
135 :
136 0 : BOOST_MOVE_FORCEINLINE explicit unique_ptr_data(P p) BOOST_NOEXCEPT
137 0 : : D(), m_p(p)
138 : {}
139 :
140 : BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT
141 : : D(d1), m_p(p)
142 : {}
143 :
144 : template <class U>
145 : BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, BOOST_FWD_REF(U) d) BOOST_NOEXCEPT
146 : : D(::boost::forward<U>(d)), m_p(p)
147 : {}
148 :
149 0 : BOOST_MOVE_FORCEINLINE del_ref deleter() BOOST_NOEXCEPT { return static_cast<del_ref>(*this); }
150 : BOOST_MOVE_FORCEINLINE 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 : < ::boost::has_move_emulation_enabled<T>::value && !bmupmu::is_reference<T>::value
260 : , ::boost::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.
392 : BOOST_MOVE_FORCEINLINE 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 : //!
403 : BOOST_MOVE_FORCEINLINE 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 0 : BOOST_MOVE_FORCEINLINE 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 0 : : 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(( !::boost::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 : BOOST_MOVE_FORCEINLINE 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(( !::boost::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>
477 : BOOST_MOVE_FORCEINLINE 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 : BOOST_MOVE_FORCEINLINE 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, ::boost::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(( !::boost::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>
515 : BOOST_MOVE_FORCEINLINE unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type2) d2) BOOST_NOEXCEPT
516 : : m_data(pointer(), ::boost::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.
529 : BOOST_MOVE_FORCEINLINE unique_ptr(BOOST_RV_REF(unique_ptr) u) BOOST_NOEXCEPT
530 : : m_data(u.release(), ::boost::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 : BOOST_MOVE_FORCEINLINE 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(), ::boost::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(( !::boost::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
566 0 : ~unique_ptr()
567 0 : { 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.
578 : unique_ptr& operator=(BOOST_RV_REF(unique_ptr) u) BOOST_NOEXCEPT
579 : {
580 : this->reset(u.release());
581 : m_data.deleter() = ::boost::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>
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() = ::boost::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.
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.
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.
632 : BOOST_MOVE_FORCEINLINE 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.
647 : BOOST_MOVE_FORCEINLINE 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 : //!
656 0 : BOOST_MOVE_FORCEINLINE pointer get() const BOOST_NOEXCEPT
657 : { return m_data.m_p; }
658 :
659 : //! <b>Returns</b>: A reference to the stored deleter.
660 : //!
661 : BOOST_MOVE_FORCEINLINE 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 : //!
667 : BOOST_MOVE_FORCEINLINE 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 : //!
674 : BOOST_MOVE_FORCEINLINE explicit operator bool
675 : #else
676 : BOOST_MOVE_FORCEINLINE 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.
688 0 : BOOST_MOVE_FORCEINLINE pointer release() BOOST_NOEXCEPT
689 : {
690 : const pointer tmp = m_data.m_p;
691 0 : 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>
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(( !::boost::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.
730 : void reset() BOOST_NOEXCEPT
731 : { this->reset(pointer()); }
732 :
733 : //! <b>Effects</b>: Same as <tt>reset()</tt>
734 : //!
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.
741 : void swap(unique_ptr& u) BOOST_NOEXCEPT
742 : {
743 : ::boost::adl_move_swap(m_data.m_p, u.m_data.m_p);
744 : ::boost::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>
751 : BOOST_MOVE_FORCEINLINE 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>
757 : BOOST_MOVE_FORCEINLINE 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>
763 : BOOST_MOVE_FORCEINLINE 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>
771 : BOOST_MOVE_FORCEINLINE 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>
777 : BOOST_MOVE_FORCEINLINE 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>
783 : BOOST_MOVE_FORCEINLINE 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>
789 : BOOST_MOVE_FORCEINLINE 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>
795 : BOOST_MOVE_FORCEINLINE 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>
801 : BOOST_MOVE_FORCEINLINE 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>
807 : BOOST_MOVE_FORCEINLINE 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>
813 : BOOST_MOVE_FORCEINLINE 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>
820 : BOOST_MOVE_FORCEINLINE 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>
827 : BOOST_MOVE_FORCEINLINE 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>
833 : BOOST_MOVE_FORCEINLINE 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>
839 : BOOST_MOVE_FORCEINLINE 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>
845 : BOOST_MOVE_FORCEINLINE 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>
851 : BOOST_MOVE_FORCEINLINE 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>
857 : BOOST_MOVE_FORCEINLINE 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>
863 : BOOST_MOVE_FORCEINLINE 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 boost{
868 :
869 : #include <boost/move/detail/config_end.hpp>
870 :
871 : #endif //#ifndef BOOST_MOVE_UNIQUE_PTR_HPP_INCLUDED
|