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 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 | unique_ptr_data() BOOST_NOEXCEPT |
97 | : m_p(), d() |
98 | {} |
99 | |
100 | explicit unique_ptr_data(P p) BOOST_NOEXCEPT |
101 | : m_p(p), d() |
102 | {} |
103 | |
104 | unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT |
105 | : m_p(p), d(d1) |
106 | {} |
107 | |
108 | template <class U> |
109 | unique_ptr_data(P p, BOOST_FWD_REF(U) d1) BOOST_NOEXCEPT |
110 | : m_p(p), d(::boost::forward<U>(d1)) |
111 | {} |
112 | |
113 | del_ref deleter() { return d; } |
114 | 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 | unique_ptr_data() BOOST_NOEXCEPT |
133 | : D(), m_p() |
134 | {} |
135 | |
136 | explicit unique_ptr_data(P p) BOOST_NOEXCEPT |
137 | : D(), m_p(p) |
138 | {} |
139 | |
140 | unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT |
141 | : D(d1), m_p(p) |
142 | {} |
143 | |
144 | template <class U> |
145 | unique_ptr_data(P p, BOOST_FWD_REF(U) d) BOOST_NOEXCEPT |
146 | : D(::boost::forward<U>(d)), m_p(p) |
147 | {} |
148 | |
149 | del_ref deleter() BOOST_NOEXCEPT { return static_cast<del_ref>(*this); } |
150 | 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_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_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(( !::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 | 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 | 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, ::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 | 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 | 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 | 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 | ~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. |
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_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 | 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 | 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_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_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 | 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. |
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> |
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 | 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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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 boost{ |
868 | |
869 | #include <boost/move/detail/config_end.hpp> |
870 | |
871 | #endif //#ifndef BOOST_MOVE_UNIQUE_PTR_HPP_INCLUDED |
872 | |