1 | // unique_ptr implementation -*- C++ -*- |
2 | |
3 | // Copyright (C) 2008-2019 Free Software Foundation, Inc. |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free |
6 | // software; you can redistribute it and/or modify it under the |
7 | // terms of the GNU General Public License as published by the |
8 | // Free Software Foundation; either version 3, or (at your option) |
9 | // any later version. |
10 | |
11 | // This library is distributed in the hope that it will be useful, |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | // GNU General Public License for more details. |
15 | |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version |
18 | // 3.1, as published by the Free Software Foundation. |
19 | |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
23 | // <http://www.gnu.org/licenses/>. |
24 | |
25 | /** @file bits/unique_ptr.h |
26 | * This is an internal header file, included by other library headers. |
27 | * Do not attempt to use it directly. @headername{memory} |
28 | */ |
29 | |
30 | #ifndef _UNIQUE_PTR_H |
31 | #define _UNIQUE_PTR_H 1 |
32 | |
33 | #include <bits/c++config.h> |
34 | #include <debug/assertions.h> |
35 | #include <type_traits> |
36 | #include <utility> |
37 | #include <tuple> |
38 | #include <bits/stl_function.h> |
39 | #include <bits/functional_hash.h> |
40 | |
41 | namespace std _GLIBCXX_VISIBILITY(default) |
42 | { |
43 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
44 | |
45 | /** |
46 | * @addtogroup pointer_abstractions |
47 | * @{ |
48 | */ |
49 | |
50 | #if _GLIBCXX_USE_DEPRECATED |
51 | #pragma GCC diagnostic push |
52 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
53 | template<typename> class auto_ptr; |
54 | #pragma GCC diagnostic pop |
55 | #endif |
56 | |
57 | /// Primary template of default_delete, used by unique_ptr |
58 | template<typename _Tp> |
59 | struct default_delete |
60 | { |
61 | /// Default constructor |
62 | constexpr default_delete() noexcept = default; |
63 | |
64 | /** @brief Converting constructor. |
65 | * |
66 | * Allows conversion from a deleter for arrays of another type, @p _Up, |
67 | * only if @p _Up* is convertible to @p _Tp*. |
68 | */ |
69 | template<typename _Up, typename = typename |
70 | enable_if<is_convertible<_Up*, _Tp*>::value>::type> |
71 | default_delete(const default_delete<_Up>&) noexcept { } |
72 | |
73 | /// Calls @c delete @p __ptr |
74 | void |
75 | operator()(_Tp* __ptr) const |
76 | { |
77 | static_assert(!is_void<_Tp>::value, |
78 | "can't delete pointer to incomplete type" ); |
79 | static_assert(sizeof(_Tp)>0, |
80 | "can't delete pointer to incomplete type" ); |
81 | delete __ptr; |
82 | } |
83 | }; |
84 | |
85 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
86 | // DR 740 - omit specialization for array objects with a compile time length |
87 | /// Specialization for arrays, default_delete. |
88 | template<typename _Tp> |
89 | struct default_delete<_Tp[]> |
90 | { |
91 | public: |
92 | /// Default constructor |
93 | constexpr default_delete() noexcept = default; |
94 | |
95 | /** @brief Converting constructor. |
96 | * |
97 | * Allows conversion from a deleter for arrays of another type, such as |
98 | * a const-qualified version of @p _Tp. |
99 | * |
100 | * Conversions from types derived from @c _Tp are not allowed because |
101 | * it is unsafe to @c delete[] an array of derived types through a |
102 | * pointer to the base type. |
103 | */ |
104 | template<typename _Up, typename = typename |
105 | enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type> |
106 | default_delete(const default_delete<_Up[]>&) noexcept { } |
107 | |
108 | /// Calls @c delete[] @p __ptr |
109 | template<typename _Up> |
110 | typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type |
111 | operator()(_Up* __ptr) const |
112 | { |
113 | static_assert(sizeof(_Tp)>0, |
114 | "can't delete pointer to incomplete type" ); |
115 | delete [] __ptr; |
116 | } |
117 | }; |
118 | |
119 | template <typename _Tp, typename _Dp> |
120 | class __uniq_ptr_impl |
121 | { |
122 | template <typename _Up, typename _Ep, typename = void> |
123 | struct _Ptr |
124 | { |
125 | using type = _Up*; |
126 | }; |
127 | |
128 | template <typename _Up, typename _Ep> |
129 | struct |
130 | _Ptr<_Up, _Ep, __void_t<typename remove_reference<_Ep>::type::pointer>> |
131 | { |
132 | using type = typename remove_reference<_Ep>::type::pointer; |
133 | }; |
134 | |
135 | public: |
136 | using _DeleterConstraint = enable_if< |
137 | __and_<__not_<is_pointer<_Dp>>, |
138 | is_default_constructible<_Dp>>::value>; |
139 | |
140 | using pointer = typename _Ptr<_Tp, _Dp>::type; |
141 | |
142 | static_assert( !is_rvalue_reference<_Dp>::value, |
143 | "unique_ptr's deleter type must be a function object type" |
144 | " or an lvalue reference type" ); |
145 | |
146 | __uniq_ptr_impl() = default; |
147 | __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; } |
148 | |
149 | template<typename _Del> |
150 | __uniq_ptr_impl(pointer __p, _Del&& __d) |
151 | : _M_t(__p, std::forward<_Del>(__d)) { } |
152 | |
153 | pointer& _M_ptr() { return std::get<0>(_M_t); } |
154 | pointer _M_ptr() const { return std::get<0>(_M_t); } |
155 | _Dp& _M_deleter() { return std::get<1>(_M_t); } |
156 | const _Dp& _M_deleter() const { return std::get<1>(_M_t); } |
157 | |
158 | void |
159 | swap(__uniq_ptr_impl& __rhs) noexcept |
160 | { |
161 | using std::swap; |
162 | swap(this->_M_ptr(), __rhs._M_ptr()); |
163 | swap(this->_M_deleter(), __rhs._M_deleter()); |
164 | } |
165 | |
166 | private: |
167 | tuple<pointer, _Dp> _M_t; |
168 | }; |
169 | |
170 | /// 20.7.1.2 unique_ptr for single objects. |
171 | template <typename _Tp, typename _Dp = default_delete<_Tp>> |
172 | class unique_ptr |
173 | { |
174 | template <typename _Up> |
175 | using _DeleterConstraint = |
176 | typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; |
177 | |
178 | __uniq_ptr_impl<_Tp, _Dp> _M_t; |
179 | |
180 | public: |
181 | using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; |
182 | using element_type = _Tp; |
183 | using deleter_type = _Dp; |
184 | |
185 | private: |
186 | // helper template for detecting a safe conversion from another |
187 | // unique_ptr |
188 | template<typename _Up, typename _Ep> |
189 | using __safe_conversion_up = __and_< |
190 | is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>, |
191 | __not_<is_array<_Up>> |
192 | >; |
193 | |
194 | public: |
195 | // Constructors. |
196 | |
197 | /// Default constructor, creates a unique_ptr that owns nothing. |
198 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
199 | constexpr unique_ptr() noexcept |
200 | : _M_t() |
201 | { } |
202 | |
203 | /** Takes ownership of a pointer. |
204 | * |
205 | * @param __p A pointer to an object of @c element_type |
206 | * |
207 | * The deleter will be value-initialized. |
208 | */ |
209 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
210 | explicit |
211 | unique_ptr(pointer __p) noexcept |
212 | : _M_t(__p) |
213 | { } |
214 | |
215 | /** Takes ownership of a pointer. |
216 | * |
217 | * @param __p A pointer to an object of @c element_type |
218 | * @param __d A reference to a deleter. |
219 | * |
220 | * The deleter will be initialized with @p __d |
221 | */ |
222 | template<typename _Del = deleter_type, |
223 | typename = _Require<is_copy_constructible<_Del>>> |
224 | unique_ptr(pointer __p, const deleter_type& __d) noexcept |
225 | : _M_t(__p, __d) { } |
226 | |
227 | /** Takes ownership of a pointer. |
228 | * |
229 | * @param __p A pointer to an object of @c element_type |
230 | * @param __d An rvalue reference to a (non-reference) deleter. |
231 | * |
232 | * The deleter will be initialized with @p std::move(__d) |
233 | */ |
234 | template<typename _Del = deleter_type, |
235 | typename = _Require<is_move_constructible<_Del>>> |
236 | unique_ptr(pointer __p, |
237 | __enable_if_t<!is_lvalue_reference<_Del>::value, |
238 | _Del&&> __d) noexcept |
239 | : _M_t(__p, std::move(__d)) |
240 | { } |
241 | |
242 | template<typename _Del = deleter_type, |
243 | typename _DelUnref = typename remove_reference<_Del>::type> |
244 | unique_ptr(pointer, |
245 | __enable_if_t<is_lvalue_reference<_Del>::value, |
246 | _DelUnref&&>) = delete; |
247 | |
248 | /// Creates a unique_ptr that owns nothing. |
249 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
250 | constexpr unique_ptr(nullptr_t) noexcept |
251 | : _M_t() |
252 | { } |
253 | |
254 | // Move constructors. |
255 | |
256 | /// Move constructor. |
257 | unique_ptr(unique_ptr&& __u) noexcept |
258 | : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } |
259 | |
260 | /** @brief Converting constructor from another type |
261 | * |
262 | * Requires that the pointer owned by @p __u is convertible to the |
263 | * type of pointer owned by this object, @p __u does not own an array, |
264 | * and @p __u has a compatible deleter type. |
265 | */ |
266 | template<typename _Up, typename _Ep, typename = _Require< |
267 | __safe_conversion_up<_Up, _Ep>, |
268 | typename conditional<is_reference<_Dp>::value, |
269 | is_same<_Ep, _Dp>, |
270 | is_convertible<_Ep, _Dp>>::type>> |
271 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept |
272 | : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) |
273 | { } |
274 | |
275 | #if _GLIBCXX_USE_DEPRECATED |
276 | #pragma GCC diagnostic push |
277 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
278 | /// Converting constructor from @c auto_ptr |
279 | template<typename _Up, typename = _Require< |
280 | is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>> |
281 | unique_ptr(auto_ptr<_Up>&& __u) noexcept; |
282 | #pragma GCC diagnostic pop |
283 | #endif |
284 | |
285 | /// Destructor, invokes the deleter if the stored pointer is not null. |
286 | ~unique_ptr() noexcept |
287 | { |
288 | static_assert(__is_invocable<deleter_type&, pointer>::value, |
289 | "unique_ptr's deleter must be invocable with a pointer" ); |
290 | auto& __ptr = _M_t._M_ptr(); |
291 | if (__ptr != nullptr) |
292 | get_deleter()(std::move(__ptr)); |
293 | __ptr = pointer(); |
294 | } |
295 | |
296 | // Assignment. |
297 | |
298 | /** @brief Move assignment operator. |
299 | * |
300 | * @param __u The object to transfer ownership from. |
301 | * |
302 | * Invokes the deleter first if this object owns a pointer. |
303 | */ |
304 | unique_ptr& |
305 | operator=(unique_ptr&& __u) noexcept |
306 | { |
307 | reset(p: __u.release()); |
308 | get_deleter() = std::forward<deleter_type>(__u.get_deleter()); |
309 | return *this; |
310 | } |
311 | |
312 | /** @brief Assignment from another type. |
313 | * |
314 | * @param __u The object to transfer ownership from, which owns a |
315 | * convertible pointer to a non-array object. |
316 | * |
317 | * Invokes the deleter first if this object owns a pointer. |
318 | */ |
319 | template<typename _Up, typename _Ep> |
320 | typename enable_if< __and_< |
321 | __safe_conversion_up<_Up, _Ep>, |
322 | is_assignable<deleter_type&, _Ep&&> |
323 | >::value, |
324 | unique_ptr&>::type |
325 | operator=(unique_ptr<_Up, _Ep>&& __u) noexcept |
326 | { |
327 | reset(p: __u.release()); |
328 | get_deleter() = std::forward<_Ep>(__u.get_deleter()); |
329 | return *this; |
330 | } |
331 | |
332 | /// Reset the %unique_ptr to empty, invoking the deleter if necessary. |
333 | unique_ptr& |
334 | operator=(nullptr_t) noexcept |
335 | { |
336 | reset(); |
337 | return *this; |
338 | } |
339 | |
340 | // Observers. |
341 | |
342 | /// Dereference the stored pointer. |
343 | typename add_lvalue_reference<element_type>::type |
344 | operator*() const |
345 | { |
346 | __glibcxx_assert(get() != pointer()); |
347 | return *get(); |
348 | } |
349 | |
350 | /// Return the stored pointer. |
351 | pointer |
352 | operator->() const noexcept |
353 | { |
354 | _GLIBCXX_DEBUG_PEDASSERT(get() != pointer()); |
355 | return get(); |
356 | } |
357 | |
358 | /// Return the stored pointer. |
359 | pointer |
360 | get() const noexcept |
361 | { return _M_t._M_ptr(); } |
362 | |
363 | /// Return a reference to the stored deleter. |
364 | deleter_type& |
365 | get_deleter() noexcept |
366 | { return _M_t._M_deleter(); } |
367 | |
368 | /// Return a reference to the stored deleter. |
369 | const deleter_type& |
370 | get_deleter() const noexcept |
371 | { return _M_t._M_deleter(); } |
372 | |
373 | /// Return @c true if the stored pointer is not null. |
374 | explicit operator bool() const noexcept |
375 | { return get() == pointer() ? false : true; } |
376 | |
377 | // Modifiers. |
378 | |
379 | /// Release ownership of any stored pointer. |
380 | pointer |
381 | release() noexcept |
382 | { |
383 | pointer __p = get(); |
384 | _M_t._M_ptr() = pointer(); |
385 | return __p; |
386 | } |
387 | |
388 | /** @brief Replace the stored pointer. |
389 | * |
390 | * @param __p The new pointer to store. |
391 | * |
392 | * The deleter will be invoked if a pointer is already owned. |
393 | */ |
394 | void |
395 | reset(pointer __p = pointer()) noexcept |
396 | { |
397 | static_assert(__is_invocable<deleter_type&, pointer>::value, |
398 | "unique_ptr's deleter must be invocable with a pointer" ); |
399 | using std::swap; |
400 | swap(_M_t._M_ptr(), __p); |
401 | if (__p != pointer()) |
402 | get_deleter()(std::move(__p)); |
403 | } |
404 | |
405 | /// Exchange the pointer and deleter with another object. |
406 | void |
407 | swap(unique_ptr& __u) noexcept |
408 | { |
409 | static_assert(__is_swappable<_Dp>::value, "deleter must be swappable" ); |
410 | _M_t.swap(__u._M_t); |
411 | } |
412 | |
413 | // Disable copy from lvalue. |
414 | unique_ptr(const unique_ptr&) = delete; |
415 | unique_ptr& operator=(const unique_ptr&) = delete; |
416 | }; |
417 | |
418 | /// 20.7.1.3 unique_ptr for array objects with a runtime length |
419 | // [unique.ptr.runtime] |
420 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
421 | // DR 740 - omit specialization for array objects with a compile time length |
422 | template<typename _Tp, typename _Dp> |
423 | class unique_ptr<_Tp[], _Dp> |
424 | { |
425 | template <typename _Up> |
426 | using _DeleterConstraint = |
427 | typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; |
428 | |
429 | __uniq_ptr_impl<_Tp, _Dp> _M_t; |
430 | |
431 | template<typename _Up> |
432 | using __remove_cv = typename remove_cv<_Up>::type; |
433 | |
434 | // like is_base_of<_Tp, _Up> but false if unqualified types are the same |
435 | template<typename _Up> |
436 | using __is_derived_Tp |
437 | = __and_< is_base_of<_Tp, _Up>, |
438 | __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >; |
439 | |
440 | public: |
441 | using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; |
442 | using element_type = _Tp; |
443 | using deleter_type = _Dp; |
444 | |
445 | // helper template for detecting a safe conversion from another |
446 | // unique_ptr |
447 | template<typename _Up, typename _Ep, |
448 | typename _UPtr = unique_ptr<_Up, _Ep>, |
449 | typename _UP_pointer = typename _UPtr::pointer, |
450 | typename _UP_element_type = typename _UPtr::element_type> |
451 | using __safe_conversion_up = __and_< |
452 | is_array<_Up>, |
453 | is_same<pointer, element_type*>, |
454 | is_same<_UP_pointer, _UP_element_type*>, |
455 | is_convertible<_UP_element_type(*)[], element_type(*)[]> |
456 | >; |
457 | |
458 | // helper template for detecting a safe conversion from a raw pointer |
459 | template<typename _Up> |
460 | using __safe_conversion_raw = __and_< |
461 | __or_<__or_<is_same<_Up, pointer>, |
462 | is_same<_Up, nullptr_t>>, |
463 | __and_<is_pointer<_Up>, |
464 | is_same<pointer, element_type*>, |
465 | is_convertible< |
466 | typename remove_pointer<_Up>::type(*)[], |
467 | element_type(*)[]> |
468 | > |
469 | > |
470 | >; |
471 | |
472 | // Constructors. |
473 | |
474 | /// Default constructor, creates a unique_ptr that owns nothing. |
475 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
476 | constexpr unique_ptr() noexcept |
477 | : _M_t() |
478 | { } |
479 | |
480 | /** Takes ownership of a pointer. |
481 | * |
482 | * @param __p A pointer to an array of a type safely convertible |
483 | * to an array of @c element_type |
484 | * |
485 | * The deleter will be value-initialized. |
486 | */ |
487 | template<typename _Up, |
488 | typename _Vp = _Dp, |
489 | typename = _DeleterConstraint<_Vp>, |
490 | typename = typename enable_if< |
491 | __safe_conversion_raw<_Up>::value, bool>::type> |
492 | explicit |
493 | unique_ptr(_Up __p) noexcept |
494 | : _M_t(__p) |
495 | { } |
496 | |
497 | /** Takes ownership of a pointer. |
498 | * |
499 | * @param __p A pointer to an array of a type safely convertible |
500 | * to an array of @c element_type |
501 | * @param __d A reference to a deleter. |
502 | * |
503 | * The deleter will be initialized with @p __d |
504 | */ |
505 | template<typename _Up, typename _Del = deleter_type, |
506 | typename = _Require<__safe_conversion_raw<_Up>, |
507 | is_copy_constructible<_Del>>> |
508 | unique_ptr(_Up __p, const deleter_type& __d) noexcept |
509 | : _M_t(__p, __d) { } |
510 | |
511 | /** Takes ownership of a pointer. |
512 | * |
513 | * @param __p A pointer to an array of a type safely convertible |
514 | * to an array of @c element_type |
515 | * @param __d A reference to a deleter. |
516 | * |
517 | * The deleter will be initialized with @p std::move(__d) |
518 | */ |
519 | template<typename _Up, typename _Del = deleter_type, |
520 | typename = _Require<__safe_conversion_raw<_Up>, |
521 | is_move_constructible<_Del>>> |
522 | unique_ptr(_Up __p, |
523 | __enable_if_t<!is_lvalue_reference<_Del>::value, |
524 | _Del&&> __d) noexcept |
525 | : _M_t(std::move(__p), std::move(__d)) |
526 | { } |
527 | |
528 | template<typename _Up, typename _Del = deleter_type, |
529 | typename _DelUnref = typename remove_reference<_Del>::type, |
530 | typename = _Require<__safe_conversion_raw<_Up>>> |
531 | unique_ptr(_Up, |
532 | __enable_if_t<is_lvalue_reference<_Del>::value, |
533 | _DelUnref&&>) = delete; |
534 | |
535 | /// Move constructor. |
536 | unique_ptr(unique_ptr&& __u) noexcept |
537 | : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } |
538 | |
539 | /// Creates a unique_ptr that owns nothing. |
540 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
541 | constexpr unique_ptr(nullptr_t) noexcept |
542 | : _M_t() |
543 | { } |
544 | |
545 | template<typename _Up, typename _Ep, typename = _Require< |
546 | __safe_conversion_up<_Up, _Ep>, |
547 | typename conditional<is_reference<_Dp>::value, |
548 | is_same<_Ep, _Dp>, |
549 | is_convertible<_Ep, _Dp>>::type>> |
550 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept |
551 | : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) |
552 | { } |
553 | |
554 | /// Destructor, invokes the deleter if the stored pointer is not null. |
555 | ~unique_ptr() |
556 | { |
557 | auto& __ptr = _M_t._M_ptr(); |
558 | if (__ptr != nullptr) |
559 | get_deleter()(__ptr); |
560 | __ptr = pointer(); |
561 | } |
562 | |
563 | // Assignment. |
564 | |
565 | /** @brief Move assignment operator. |
566 | * |
567 | * @param __u The object to transfer ownership from. |
568 | * |
569 | * Invokes the deleter first if this object owns a pointer. |
570 | */ |
571 | unique_ptr& |
572 | operator=(unique_ptr&& __u) noexcept |
573 | { |
574 | reset(__u.release()); |
575 | get_deleter() = std::forward<deleter_type>(__u.get_deleter()); |
576 | return *this; |
577 | } |
578 | |
579 | /** @brief Assignment from another type. |
580 | * |
581 | * @param __u The object to transfer ownership from, which owns a |
582 | * convertible pointer to an array object. |
583 | * |
584 | * Invokes the deleter first if this object owns a pointer. |
585 | */ |
586 | template<typename _Up, typename _Ep> |
587 | typename |
588 | enable_if<__and_<__safe_conversion_up<_Up, _Ep>, |
589 | is_assignable<deleter_type&, _Ep&&> |
590 | >::value, |
591 | unique_ptr&>::type |
592 | operator=(unique_ptr<_Up, _Ep>&& __u) noexcept |
593 | { |
594 | reset(__u.release()); |
595 | get_deleter() = std::forward<_Ep>(__u.get_deleter()); |
596 | return *this; |
597 | } |
598 | |
599 | /// Reset the %unique_ptr to empty, invoking the deleter if necessary. |
600 | unique_ptr& |
601 | operator=(nullptr_t) noexcept |
602 | { |
603 | reset(); |
604 | return *this; |
605 | } |
606 | |
607 | // Observers. |
608 | |
609 | /// Access an element of owned array. |
610 | typename std::add_lvalue_reference<element_type>::type |
611 | operator[](size_t __i) const |
612 | { |
613 | __glibcxx_assert(get() != pointer()); |
614 | return get()[__i]; |
615 | } |
616 | |
617 | /// Return the stored pointer. |
618 | pointer |
619 | get() const noexcept |
620 | { return _M_t._M_ptr(); } |
621 | |
622 | /// Return a reference to the stored deleter. |
623 | deleter_type& |
624 | get_deleter() noexcept |
625 | { return _M_t._M_deleter(); } |
626 | |
627 | /// Return a reference to the stored deleter. |
628 | const deleter_type& |
629 | get_deleter() const noexcept |
630 | { return _M_t._M_deleter(); } |
631 | |
632 | /// Return @c true if the stored pointer is not null. |
633 | explicit operator bool() const noexcept |
634 | { return get() == pointer() ? false : true; } |
635 | |
636 | // Modifiers. |
637 | |
638 | /// Release ownership of any stored pointer. |
639 | pointer |
640 | release() noexcept |
641 | { |
642 | pointer __p = get(); |
643 | _M_t._M_ptr() = pointer(); |
644 | return __p; |
645 | } |
646 | |
647 | /** @brief Replace the stored pointer. |
648 | * |
649 | * @param __p The new pointer to store. |
650 | * |
651 | * The deleter will be invoked if a pointer is already owned. |
652 | */ |
653 | template <typename _Up, |
654 | typename = _Require< |
655 | __or_<is_same<_Up, pointer>, |
656 | __and_<is_same<pointer, element_type*>, |
657 | is_pointer<_Up>, |
658 | is_convertible< |
659 | typename remove_pointer<_Up>::type(*)[], |
660 | element_type(*)[] |
661 | > |
662 | > |
663 | > |
664 | >> |
665 | void |
666 | reset(_Up __p) noexcept |
667 | { |
668 | pointer __ptr = __p; |
669 | using std::swap; |
670 | swap(_M_t._M_ptr(), __ptr); |
671 | if (__ptr != nullptr) |
672 | get_deleter()(__ptr); |
673 | } |
674 | |
675 | void reset(nullptr_t = nullptr) noexcept |
676 | { |
677 | reset(pointer()); |
678 | } |
679 | |
680 | /// Exchange the pointer and deleter with another object. |
681 | void |
682 | swap(unique_ptr& __u) noexcept |
683 | { |
684 | static_assert(__is_swappable<_Dp>::value, "deleter must be swappable" ); |
685 | _M_t.swap(__u._M_t); |
686 | } |
687 | |
688 | // Disable copy from lvalue. |
689 | unique_ptr(const unique_ptr&) = delete; |
690 | unique_ptr& operator=(const unique_ptr&) = delete; |
691 | }; |
692 | |
693 | template<typename _Tp, typename _Dp> |
694 | inline |
695 | #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 |
696 | // Constrained free swap overload, see p0185r1 |
697 | typename enable_if<__is_swappable<_Dp>::value>::type |
698 | #else |
699 | void |
700 | #endif |
701 | swap(unique_ptr<_Tp, _Dp>& __x, |
702 | unique_ptr<_Tp, _Dp>& __y) noexcept |
703 | { __x.swap(__y); } |
704 | |
705 | #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 |
706 | template<typename _Tp, typename _Dp> |
707 | typename enable_if<!__is_swappable<_Dp>::value>::type |
708 | swap(unique_ptr<_Tp, _Dp>&, |
709 | unique_ptr<_Tp, _Dp>&) = delete; |
710 | #endif |
711 | |
712 | template<typename _Tp, typename _Dp, |
713 | typename _Up, typename _Ep> |
714 | _GLIBCXX_NODISCARD inline bool |
715 | operator==(const unique_ptr<_Tp, _Dp>& __x, |
716 | const unique_ptr<_Up, _Ep>& __y) |
717 | { return __x.get() == __y.get(); } |
718 | |
719 | template<typename _Tp, typename _Dp> |
720 | _GLIBCXX_NODISCARD inline bool |
721 | operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept |
722 | { return !__x; } |
723 | |
724 | template<typename _Tp, typename _Dp> |
725 | _GLIBCXX_NODISCARD inline bool |
726 | operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept |
727 | { return !__x; } |
728 | |
729 | template<typename _Tp, typename _Dp, |
730 | typename _Up, typename _Ep> |
731 | _GLIBCXX_NODISCARD inline bool |
732 | operator!=(const unique_ptr<_Tp, _Dp>& __x, |
733 | const unique_ptr<_Up, _Ep>& __y) |
734 | { return __x.get() != __y.get(); } |
735 | |
736 | template<typename _Tp, typename _Dp> |
737 | _GLIBCXX_NODISCARD inline bool |
738 | operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept |
739 | { return (bool)__x; } |
740 | |
741 | template<typename _Tp, typename _Dp> |
742 | _GLIBCXX_NODISCARD inline bool |
743 | operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept |
744 | { return (bool)__x; } |
745 | |
746 | template<typename _Tp, typename _Dp, |
747 | typename _Up, typename _Ep> |
748 | _GLIBCXX_NODISCARD inline bool |
749 | operator<(const unique_ptr<_Tp, _Dp>& __x, |
750 | const unique_ptr<_Up, _Ep>& __y) |
751 | { |
752 | typedef typename |
753 | std::common_type<typename unique_ptr<_Tp, _Dp>::pointer, |
754 | typename unique_ptr<_Up, _Ep>::pointer>::type _CT; |
755 | return std::less<_CT>()(__x.get(), __y.get()); |
756 | } |
757 | |
758 | template<typename _Tp, typename _Dp> |
759 | _GLIBCXX_NODISCARD inline bool |
760 | operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
761 | { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(), |
762 | nullptr); } |
763 | |
764 | template<typename _Tp, typename _Dp> |
765 | _GLIBCXX_NODISCARD inline bool |
766 | operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
767 | { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr, |
768 | __x.get()); } |
769 | |
770 | template<typename _Tp, typename _Dp, |
771 | typename _Up, typename _Ep> |
772 | _GLIBCXX_NODISCARD inline bool |
773 | operator<=(const unique_ptr<_Tp, _Dp>& __x, |
774 | const unique_ptr<_Up, _Ep>& __y) |
775 | { return !(__y < __x); } |
776 | |
777 | template<typename _Tp, typename _Dp> |
778 | _GLIBCXX_NODISCARD inline bool |
779 | operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
780 | { return !(nullptr < __x); } |
781 | |
782 | template<typename _Tp, typename _Dp> |
783 | _GLIBCXX_NODISCARD inline bool |
784 | operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
785 | { return !(__x < nullptr); } |
786 | |
787 | template<typename _Tp, typename _Dp, |
788 | typename _Up, typename _Ep> |
789 | _GLIBCXX_NODISCARD inline bool |
790 | operator>(const unique_ptr<_Tp, _Dp>& __x, |
791 | const unique_ptr<_Up, _Ep>& __y) |
792 | { return (__y < __x); } |
793 | |
794 | template<typename _Tp, typename _Dp> |
795 | _GLIBCXX_NODISCARD inline bool |
796 | operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
797 | { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr, |
798 | __x.get()); } |
799 | |
800 | template<typename _Tp, typename _Dp> |
801 | _GLIBCXX_NODISCARD inline bool |
802 | operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
803 | { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(), |
804 | nullptr); } |
805 | |
806 | template<typename _Tp, typename _Dp, |
807 | typename _Up, typename _Ep> |
808 | _GLIBCXX_NODISCARD inline bool |
809 | operator>=(const unique_ptr<_Tp, _Dp>& __x, |
810 | const unique_ptr<_Up, _Ep>& __y) |
811 | { return !(__x < __y); } |
812 | |
813 | template<typename _Tp, typename _Dp> |
814 | _GLIBCXX_NODISCARD inline bool |
815 | operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
816 | { return !(__x < nullptr); } |
817 | |
818 | template<typename _Tp, typename _Dp> |
819 | _GLIBCXX_NODISCARD inline bool |
820 | operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
821 | { return !(nullptr < __x); } |
822 | |
823 | /// std::hash specialization for unique_ptr. |
824 | template<typename _Tp, typename _Dp> |
825 | struct hash<unique_ptr<_Tp, _Dp>> |
826 | : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>, |
827 | private __poison_hash<typename unique_ptr<_Tp, _Dp>::pointer> |
828 | { |
829 | size_t |
830 | operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept |
831 | { |
832 | typedef unique_ptr<_Tp, _Dp> _UP; |
833 | return std::hash<typename _UP::pointer>()(__u.get()); |
834 | } |
835 | }; |
836 | |
837 | #if __cplusplus > 201103L |
838 | |
839 | #define __cpp_lib_make_unique 201304 |
840 | |
841 | template<typename _Tp> |
842 | struct _MakeUniq |
843 | { typedef unique_ptr<_Tp> __single_object; }; |
844 | |
845 | template<typename _Tp> |
846 | struct _MakeUniq<_Tp[]> |
847 | { typedef unique_ptr<_Tp[]> __array; }; |
848 | |
849 | template<typename _Tp, size_t _Bound> |
850 | struct _MakeUniq<_Tp[_Bound]> |
851 | { struct __invalid_type { }; }; |
852 | |
853 | /// std::make_unique for single objects |
854 | template<typename _Tp, typename... _Args> |
855 | inline typename _MakeUniq<_Tp>::__single_object |
856 | make_unique(_Args&&... __args) |
857 | { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); } |
858 | |
859 | /// std::make_unique for arrays of unknown bound |
860 | template<typename _Tp> |
861 | inline typename _MakeUniq<_Tp>::__array |
862 | make_unique(size_t __num) |
863 | { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); } |
864 | |
865 | /// Disable std::make_unique for arrays of known bound |
866 | template<typename _Tp, typename... _Args> |
867 | inline typename _MakeUniq<_Tp>::__invalid_type |
868 | make_unique(_Args&&...) = delete; |
869 | #endif |
870 | |
871 | /// @} group pointer_abstractions |
872 | |
873 | #if __cplusplus >= 201703L |
874 | namespace __detail::__variant |
875 | { |
876 | template<typename> struct _Never_valueless_alt; // see <variant> |
877 | |
878 | // Provide the strong exception-safety guarantee when emplacing a |
879 | // unique_ptr into a variant. |
880 | template<typename _Tp, typename _Del> |
881 | struct _Never_valueless_alt<std::unique_ptr<_Tp, _Del>> |
882 | : std::true_type |
883 | { }; |
884 | } // namespace __detail::__variant |
885 | #endif // C++17 |
886 | |
887 | _GLIBCXX_END_NAMESPACE_VERSION |
888 | } // namespace |
889 | |
890 | #endif /* _UNIQUE_PTR_H */ |
891 | |