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 | private: |
159 | tuple<pointer, _Dp> _M_t; |
160 | }; |
161 | |
162 | /// 20.7.1.2 unique_ptr for single objects. |
163 | template <typename _Tp, typename _Dp = default_delete<_Tp>> |
164 | class unique_ptr |
165 | { |
166 | template <typename _Up> |
167 | using _DeleterConstraint = |
168 | typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; |
169 | |
170 | __uniq_ptr_impl<_Tp, _Dp> _M_t; |
171 | |
172 | public: |
173 | using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; |
174 | using element_type = _Tp; |
175 | using deleter_type = _Dp; |
176 | |
177 | private: |
178 | // helper template for detecting a safe conversion from another |
179 | // unique_ptr |
180 | template<typename _Up, typename _Ep> |
181 | using __safe_conversion_up = __and_< |
182 | is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>, |
183 | __not_<is_array<_Up>>, |
184 | __or_<__and_<is_reference<deleter_type>, |
185 | is_same<deleter_type, _Ep>>, |
186 | __and_<__not_<is_reference<deleter_type>>, |
187 | is_convertible<_Ep, deleter_type>> |
188 | > |
189 | >; |
190 | |
191 | public: |
192 | // Constructors. |
193 | |
194 | /// Default constructor, creates a unique_ptr that owns nothing. |
195 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
196 | constexpr unique_ptr() noexcept |
197 | : _M_t() |
198 | { } |
199 | |
200 | /** Takes ownership of a pointer. |
201 | * |
202 | * @param __p A pointer to an object of @c element_type |
203 | * |
204 | * The deleter will be value-initialized. |
205 | */ |
206 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
207 | explicit |
208 | unique_ptr(pointer __p) noexcept |
209 | : _M_t(__p) |
210 | { } |
211 | |
212 | /** Takes ownership of a pointer. |
213 | * |
214 | * @param __p A pointer to an object of @c element_type |
215 | * @param __d A reference to a deleter. |
216 | * |
217 | * The deleter will be initialized with @p __d |
218 | */ |
219 | template<typename _Del = deleter_type, |
220 | typename = _Require<is_copy_constructible<_Del>>> |
221 | unique_ptr(pointer __p, const deleter_type& __d) noexcept |
222 | : _M_t(__p, __d) { } |
223 | |
224 | /** Takes ownership of a pointer. |
225 | * |
226 | * @param __p A pointer to an object of @c element_type |
227 | * @param __d An rvalue reference to a (non-reference) deleter. |
228 | * |
229 | * The deleter will be initialized with @p std::move(__d) |
230 | */ |
231 | template<typename _Del = deleter_type, |
232 | typename = _Require<is_move_constructible<_Del>>> |
233 | unique_ptr(pointer __p, |
234 | __enable_if_t<!is_lvalue_reference<_Del>::value, |
235 | _Del&&> __d) noexcept |
236 | : _M_t(__p, std::move(__d)) |
237 | { } |
238 | |
239 | template<typename _Del = deleter_type, |
240 | typename _DelUnref = typename remove_reference<_Del>::type> |
241 | unique_ptr(pointer, |
242 | __enable_if_t<is_lvalue_reference<_Del>::value, |
243 | _DelUnref&&>) = delete; |
244 | |
245 | /// Creates a unique_ptr that owns nothing. |
246 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
247 | constexpr unique_ptr(nullptr_t) noexcept |
248 | : _M_t() |
249 | { } |
250 | |
251 | // Move constructors. |
252 | |
253 | /// Move constructor. |
254 | unique_ptr(unique_ptr&& __u) noexcept |
255 | : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } |
256 | |
257 | /** @brief Converting constructor from another type |
258 | * |
259 | * Requires that the pointer owned by @p __u is convertible to the |
260 | * type of pointer owned by this object, @p __u does not own an array, |
261 | * and @p __u has a compatible deleter type. |
262 | */ |
263 | template<typename _Up, typename _Ep, typename = _Require< |
264 | __safe_conversion_up<_Up, _Ep>, |
265 | typename conditional<is_reference<_Dp>::value, |
266 | is_same<_Ep, _Dp>, |
267 | is_convertible<_Ep, _Dp>>::type>> |
268 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept |
269 | : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) |
270 | { } |
271 | |
272 | #if _GLIBCXX_USE_DEPRECATED |
273 | #pragma GCC diagnostic push |
274 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
275 | /// Converting constructor from @c auto_ptr |
276 | template<typename _Up, typename = _Require< |
277 | is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>> |
278 | unique_ptr(auto_ptr<_Up>&& __u) noexcept; |
279 | #pragma GCC diagnostic pop |
280 | #endif |
281 | |
282 | /// Destructor, invokes the deleter if the stored pointer is not null. |
283 | ~unique_ptr() noexcept |
284 | { |
285 | static_assert(__is_invocable<deleter_type&, pointer>::value, |
286 | "unique_ptr's deleter must be invocable with a pointer" ); |
287 | auto& __ptr = _M_t._M_ptr(); |
288 | if (__ptr != nullptr) |
289 | get_deleter()(std::move(__ptr)); |
290 | __ptr = pointer(); |
291 | } |
292 | |
293 | // Assignment. |
294 | |
295 | /** @brief Move assignment operator. |
296 | * |
297 | * @param __u The object to transfer ownership from. |
298 | * |
299 | * Invokes the deleter first if this object owns a pointer. |
300 | */ |
301 | unique_ptr& |
302 | operator=(unique_ptr&& __u) noexcept |
303 | { |
304 | reset(__u.release()); |
305 | get_deleter() = std::forward<deleter_type>(__u.get_deleter()); |
306 | return *this; |
307 | } |
308 | |
309 | /** @brief Assignment from another type. |
310 | * |
311 | * @param __u The object to transfer ownership from, which owns a |
312 | * convertible pointer to a non-array object. |
313 | * |
314 | * Invokes the deleter first if this object owns a pointer. |
315 | */ |
316 | template<typename _Up, typename _Ep> |
317 | typename enable_if< __and_< |
318 | __safe_conversion_up<_Up, _Ep>, |
319 | is_assignable<deleter_type&, _Ep&&> |
320 | >::value, |
321 | unique_ptr&>::type |
322 | operator=(unique_ptr<_Up, _Ep>&& __u) noexcept |
323 | { |
324 | reset(__u.release()); |
325 | get_deleter() = std::forward<_Ep>(__u.get_deleter()); |
326 | return *this; |
327 | } |
328 | |
329 | /// Reset the %unique_ptr to empty, invoking the deleter if necessary. |
330 | unique_ptr& |
331 | operator=(nullptr_t) noexcept |
332 | { |
333 | reset(); |
334 | return *this; |
335 | } |
336 | |
337 | // Observers. |
338 | |
339 | /// Dereference the stored pointer. |
340 | typename add_lvalue_reference<element_type>::type |
341 | operator*() const |
342 | { |
343 | __glibcxx_assert(get() != pointer()); |
344 | return *get(); |
345 | } |
346 | |
347 | /// Return the stored pointer. |
348 | pointer |
349 | operator->() const noexcept |
350 | { |
351 | _GLIBCXX_DEBUG_PEDASSERT(get() != pointer()); |
352 | return get(); |
353 | } |
354 | |
355 | /// Return the stored pointer. |
356 | pointer |
357 | get() const noexcept |
358 | { return _M_t._M_ptr(); } |
359 | |
360 | /// Return a reference to the stored deleter. |
361 | deleter_type& |
362 | get_deleter() noexcept |
363 | { return _M_t._M_deleter(); } |
364 | |
365 | /// Return a reference to the stored deleter. |
366 | const deleter_type& |
367 | get_deleter() const noexcept |
368 | { return _M_t._M_deleter(); } |
369 | |
370 | /// Return @c true if the stored pointer is not null. |
371 | explicit operator bool() const noexcept |
372 | { return get() == pointer() ? false : true; } |
373 | |
374 | // Modifiers. |
375 | |
376 | /// Release ownership of any stored pointer. |
377 | pointer |
378 | release() noexcept |
379 | { |
380 | pointer __p = get(); |
381 | _M_t._M_ptr() = pointer(); |
382 | return __p; |
383 | } |
384 | |
385 | /** @brief Replace the stored pointer. |
386 | * |
387 | * @param __p The new pointer to store. |
388 | * |
389 | * The deleter will be invoked if a pointer is already owned. |
390 | */ |
391 | void |
392 | reset(pointer __p = pointer()) noexcept |
393 | { |
394 | static_assert(__is_invocable<deleter_type&, pointer>::value, |
395 | "unique_ptr's deleter must be invocable with a pointer" ); |
396 | using std::swap; |
397 | swap(_M_t._M_ptr(), __p); |
398 | if (__p != pointer()) |
399 | get_deleter()(std::move(__p)); |
400 | } |
401 | |
402 | /// Exchange the pointer and deleter with another object. |
403 | void |
404 | swap(unique_ptr& __u) noexcept |
405 | { |
406 | using std::swap; |
407 | swap(_M_t, __u._M_t); |
408 | } |
409 | |
410 | // Disable copy from lvalue. |
411 | unique_ptr(const unique_ptr&) = delete; |
412 | unique_ptr& operator=(const unique_ptr&) = delete; |
413 | }; |
414 | |
415 | /// 20.7.1.3 unique_ptr for array objects with a runtime length |
416 | // [unique.ptr.runtime] |
417 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
418 | // DR 740 - omit specialization for array objects with a compile time length |
419 | template<typename _Tp, typename _Dp> |
420 | class unique_ptr<_Tp[], _Dp> |
421 | { |
422 | template <typename _Up> |
423 | using _DeleterConstraint = |
424 | typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; |
425 | |
426 | __uniq_ptr_impl<_Tp, _Dp> _M_t; |
427 | |
428 | template<typename _Up> |
429 | using __remove_cv = typename remove_cv<_Up>::type; |
430 | |
431 | // like is_base_of<_Tp, _Up> but false if unqualified types are the same |
432 | template<typename _Up> |
433 | using __is_derived_Tp |
434 | = __and_< is_base_of<_Tp, _Up>, |
435 | __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >; |
436 | |
437 | public: |
438 | using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; |
439 | using element_type = _Tp; |
440 | using deleter_type = _Dp; |
441 | |
442 | // helper template for detecting a safe conversion from another |
443 | // unique_ptr |
444 | template<typename _Up, typename _Ep, |
445 | typename _Up_up = unique_ptr<_Up, _Ep>, |
446 | typename _Up_element_type = typename _Up_up::element_type> |
447 | using __safe_conversion_up = __and_< |
448 | is_array<_Up>, |
449 | is_same<pointer, element_type*>, |
450 | is_same<typename _Up_up::pointer, _Up_element_type*>, |
451 | is_convertible<_Up_element_type(*)[], element_type(*)[]>, |
452 | __or_<__and_<is_reference<deleter_type>, is_same<deleter_type, _Ep>>, |
453 | __and_<__not_<is_reference<deleter_type>>, |
454 | is_convertible<_Ep, deleter_type>>> |
455 | >; |
456 | |
457 | // helper template for detecting a safe conversion from a raw pointer |
458 | template<typename _Up> |
459 | using __safe_conversion_raw = __and_< |
460 | __or_<__or_<is_same<_Up, pointer>, |
461 | is_same<_Up, nullptr_t>>, |
462 | __and_<is_pointer<_Up>, |
463 | is_same<pointer, element_type*>, |
464 | is_convertible< |
465 | typename remove_pointer<_Up>::type(*)[], |
466 | element_type(*)[]> |
467 | > |
468 | > |
469 | >; |
470 | |
471 | // Constructors. |
472 | |
473 | /// Default constructor, creates a unique_ptr that owns nothing. |
474 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
475 | constexpr unique_ptr() noexcept |
476 | : _M_t() |
477 | { } |
478 | |
479 | /** Takes ownership of a pointer. |
480 | * |
481 | * @param __p A pointer to an array of a type safely convertible |
482 | * to an array of @c element_type |
483 | * |
484 | * The deleter will be value-initialized. |
485 | */ |
486 | template<typename _Up, |
487 | typename _Vp = _Dp, |
488 | typename = _DeleterConstraint<_Vp>, |
489 | typename = typename enable_if< |
490 | __safe_conversion_raw<_Up>::value, bool>::type> |
491 | explicit |
492 | unique_ptr(_Up __p) noexcept |
493 | : _M_t(__p) |
494 | { } |
495 | |
496 | /** Takes ownership of a pointer. |
497 | * |
498 | * @param __p A pointer to an array of a type safely convertible |
499 | * to an array of @c element_type |
500 | * @param __d A reference to a deleter. |
501 | * |
502 | * The deleter will be initialized with @p __d |
503 | */ |
504 | template<typename _Up, typename _Del = deleter_type, |
505 | typename = _Require<__safe_conversion_raw<_Up>, |
506 | is_copy_constructible<_Del>>> |
507 | unique_ptr(_Up __p, const deleter_type& __d) noexcept |
508 | : _M_t(__p, __d) { } |
509 | |
510 | /** Takes ownership of a pointer. |
511 | * |
512 | * @param __p A pointer to an array of a type safely convertible |
513 | * to an array of @c element_type |
514 | * @param __d A reference to a deleter. |
515 | * |
516 | * The deleter will be initialized with @p std::move(__d) |
517 | */ |
518 | template<typename _Up, typename _Del = deleter_type, |
519 | typename = _Require<__safe_conversion_raw<_Up>, |
520 | is_move_constructible<_Del>>> |
521 | unique_ptr(_Up __p, |
522 | __enable_if_t<!is_lvalue_reference<_Del>::value, |
523 | _Del&&> __d) noexcept |
524 | : _M_t(std::move(__p), std::move(__d)) |
525 | { } |
526 | |
527 | template<typename _Up, typename _Del = deleter_type, |
528 | typename _DelUnref = typename remove_reference<_Del>::type, |
529 | typename = _Require<__safe_conversion_raw<_Up>>> |
530 | unique_ptr(_Up, |
531 | __enable_if_t<is_lvalue_reference<_Del>::value, |
532 | _DelUnref&&>) = delete; |
533 | |
534 | /// Move constructor. |
535 | unique_ptr(unique_ptr&& __u) noexcept |
536 | : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } |
537 | |
538 | /// Creates a unique_ptr that owns nothing. |
539 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
540 | constexpr unique_ptr(nullptr_t) noexcept |
541 | : _M_t() |
542 | { } |
543 | |
544 | template<typename _Up, typename _Ep, |
545 | typename = _Require<__safe_conversion_up<_Up, _Ep>>> |
546 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept |
547 | : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) |
548 | { } |
549 | |
550 | /// Destructor, invokes the deleter if the stored pointer is not null. |
551 | ~unique_ptr() |
552 | { |
553 | auto& __ptr = _M_t._M_ptr(); |
554 | if (__ptr != nullptr) |
555 | get_deleter()(__ptr); |
556 | __ptr = pointer(); |
557 | } |
558 | |
559 | // Assignment. |
560 | |
561 | /** @brief Move assignment operator. |
562 | * |
563 | * @param __u The object to transfer ownership from. |
564 | * |
565 | * Invokes the deleter first if this object owns a pointer. |
566 | */ |
567 | unique_ptr& |
568 | operator=(unique_ptr&& __u) noexcept |
569 | { |
570 | reset(__u.release()); |
571 | get_deleter() = std::forward<deleter_type>(__u.get_deleter()); |
572 | return *this; |
573 | } |
574 | |
575 | /** @brief Assignment from another type. |
576 | * |
577 | * @param __u The object to transfer ownership from, which owns a |
578 | * convertible pointer to an array object. |
579 | * |
580 | * Invokes the deleter first if this object owns a pointer. |
581 | */ |
582 | template<typename _Up, typename _Ep> |
583 | typename |
584 | enable_if<__and_<__safe_conversion_up<_Up, _Ep>, |
585 | is_assignable<deleter_type&, _Ep&&> |
586 | >::value, |
587 | unique_ptr&>::type |
588 | operator=(unique_ptr<_Up, _Ep>&& __u) noexcept |
589 | { |
590 | reset(__u.release()); |
591 | get_deleter() = std::forward<_Ep>(__u.get_deleter()); |
592 | return *this; |
593 | } |
594 | |
595 | /// Reset the %unique_ptr to empty, invoking the deleter if necessary. |
596 | unique_ptr& |
597 | operator=(nullptr_t) noexcept |
598 | { |
599 | reset(); |
600 | return *this; |
601 | } |
602 | |
603 | // Observers. |
604 | |
605 | /// Access an element of owned array. |
606 | typename std::add_lvalue_reference<element_type>::type |
607 | operator[](size_t __i) const |
608 | { |
609 | __glibcxx_assert(get() != pointer()); |
610 | return get()[__i]; |
611 | } |
612 | |
613 | /// Return the stored pointer. |
614 | pointer |
615 | get() const noexcept |
616 | { return _M_t._M_ptr(); } |
617 | |
618 | /// Return a reference to the stored deleter. |
619 | deleter_type& |
620 | get_deleter() noexcept |
621 | { return _M_t._M_deleter(); } |
622 | |
623 | /// Return a reference to the stored deleter. |
624 | const deleter_type& |
625 | get_deleter() const noexcept |
626 | { return _M_t._M_deleter(); } |
627 | |
628 | /// Return @c true if the stored pointer is not null. |
629 | explicit operator bool() const noexcept |
630 | { return get() == pointer() ? false : true; } |
631 | |
632 | // Modifiers. |
633 | |
634 | /// Release ownership of any stored pointer. |
635 | pointer |
636 | release() noexcept |
637 | { |
638 | pointer __p = get(); |
639 | _M_t._M_ptr() = pointer(); |
640 | return __p; |
641 | } |
642 | |
643 | /** @brief Replace the stored pointer. |
644 | * |
645 | * @param __p The new pointer to store. |
646 | * |
647 | * The deleter will be invoked if a pointer is already owned. |
648 | */ |
649 | template <typename _Up, |
650 | typename = _Require< |
651 | __or_<is_same<_Up, pointer>, |
652 | __and_<is_same<pointer, element_type*>, |
653 | is_pointer<_Up>, |
654 | is_convertible< |
655 | typename remove_pointer<_Up>::type(*)[], |
656 | element_type(*)[] |
657 | > |
658 | > |
659 | > |
660 | >> |
661 | void |
662 | reset(_Up __p) noexcept |
663 | { |
664 | pointer __ptr = __p; |
665 | using std::swap; |
666 | swap(_M_t._M_ptr(), __ptr); |
667 | if (__ptr != nullptr) |
668 | get_deleter()(__ptr); |
669 | } |
670 | |
671 | void reset(nullptr_t = nullptr) noexcept |
672 | { |
673 | reset(pointer()); |
674 | } |
675 | |
676 | /// Exchange the pointer and deleter with another object. |
677 | void |
678 | swap(unique_ptr& __u) noexcept |
679 | { |
680 | using std::swap; |
681 | swap(_M_t, __u._M_t); |
682 | } |
683 | |
684 | // Disable copy from lvalue. |
685 | unique_ptr(const unique_ptr&) = delete; |
686 | unique_ptr& operator=(const unique_ptr&) = delete; |
687 | }; |
688 | |
689 | template<typename _Tp, typename _Dp> |
690 | inline |
691 | #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 |
692 | // Constrained free swap overload, see p0185r1 |
693 | typename enable_if<__is_swappable<_Dp>::value>::type |
694 | #else |
695 | void |
696 | #endif |
697 | swap(unique_ptr<_Tp, _Dp>& __x, |
698 | unique_ptr<_Tp, _Dp>& __y) noexcept |
699 | { __x.swap(__y); } |
700 | |
701 | #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 |
702 | template<typename _Tp, typename _Dp> |
703 | typename enable_if<!__is_swappable<_Dp>::value>::type |
704 | swap(unique_ptr<_Tp, _Dp>&, |
705 | unique_ptr<_Tp, _Dp>&) = delete; |
706 | #endif |
707 | |
708 | template<typename _Tp, typename _Dp, |
709 | typename _Up, typename _Ep> |
710 | _GLIBCXX_NODISCARD inline bool |
711 | operator==(const unique_ptr<_Tp, _Dp>& __x, |
712 | const unique_ptr<_Up, _Ep>& __y) |
713 | { return __x.get() == __y.get(); } |
714 | |
715 | template<typename _Tp, typename _Dp> |
716 | _GLIBCXX_NODISCARD inline bool |
717 | operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept |
718 | { return !__x; } |
719 | |
720 | template<typename _Tp, typename _Dp> |
721 | _GLIBCXX_NODISCARD inline bool |
722 | operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept |
723 | { return !__x; } |
724 | |
725 | template<typename _Tp, typename _Dp, |
726 | typename _Up, typename _Ep> |
727 | _GLIBCXX_NODISCARD inline bool |
728 | operator!=(const unique_ptr<_Tp, _Dp>& __x, |
729 | const unique_ptr<_Up, _Ep>& __y) |
730 | { return __x.get() != __y.get(); } |
731 | |
732 | template<typename _Tp, typename _Dp> |
733 | _GLIBCXX_NODISCARD inline bool |
734 | operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept |
735 | { return (bool)__x; } |
736 | |
737 | template<typename _Tp, typename _Dp> |
738 | _GLIBCXX_NODISCARD inline bool |
739 | operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept |
740 | { return (bool)__x; } |
741 | |
742 | template<typename _Tp, typename _Dp, |
743 | typename _Up, typename _Ep> |
744 | _GLIBCXX_NODISCARD inline bool |
745 | operator<(const unique_ptr<_Tp, _Dp>& __x, |
746 | const unique_ptr<_Up, _Ep>& __y) |
747 | { |
748 | typedef typename |
749 | std::common_type<typename unique_ptr<_Tp, _Dp>::pointer, |
750 | typename unique_ptr<_Up, _Ep>::pointer>::type _CT; |
751 | return std::less<_CT>()(__x.get(), __y.get()); |
752 | } |
753 | |
754 | template<typename _Tp, typename _Dp> |
755 | _GLIBCXX_NODISCARD inline bool |
756 | operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
757 | { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(), |
758 | nullptr); } |
759 | |
760 | template<typename _Tp, typename _Dp> |
761 | _GLIBCXX_NODISCARD inline bool |
762 | operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
763 | { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr, |
764 | __x.get()); } |
765 | |
766 | template<typename _Tp, typename _Dp, |
767 | typename _Up, typename _Ep> |
768 | _GLIBCXX_NODISCARD inline bool |
769 | operator<=(const unique_ptr<_Tp, _Dp>& __x, |
770 | const unique_ptr<_Up, _Ep>& __y) |
771 | { return !(__y < __x); } |
772 | |
773 | template<typename _Tp, typename _Dp> |
774 | _GLIBCXX_NODISCARD inline bool |
775 | operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
776 | { return !(nullptr < __x); } |
777 | |
778 | template<typename _Tp, typename _Dp> |
779 | _GLIBCXX_NODISCARD inline bool |
780 | operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
781 | { return !(__x < nullptr); } |
782 | |
783 | template<typename _Tp, typename _Dp, |
784 | typename _Up, typename _Ep> |
785 | _GLIBCXX_NODISCARD inline bool |
786 | operator>(const unique_ptr<_Tp, _Dp>& __x, |
787 | const unique_ptr<_Up, _Ep>& __y) |
788 | { return (__y < __x); } |
789 | |
790 | template<typename _Tp, typename _Dp> |
791 | _GLIBCXX_NODISCARD inline bool |
792 | operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
793 | { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr, |
794 | __x.get()); } |
795 | |
796 | template<typename _Tp, typename _Dp> |
797 | _GLIBCXX_NODISCARD inline bool |
798 | operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
799 | { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(), |
800 | nullptr); } |
801 | |
802 | template<typename _Tp, typename _Dp, |
803 | typename _Up, typename _Ep> |
804 | _GLIBCXX_NODISCARD inline bool |
805 | operator>=(const unique_ptr<_Tp, _Dp>& __x, |
806 | const unique_ptr<_Up, _Ep>& __y) |
807 | { return !(__x < __y); } |
808 | |
809 | template<typename _Tp, typename _Dp> |
810 | _GLIBCXX_NODISCARD inline bool |
811 | operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
812 | { return !(__x < nullptr); } |
813 | |
814 | template<typename _Tp, typename _Dp> |
815 | _GLIBCXX_NODISCARD inline bool |
816 | operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
817 | { return !(nullptr < __x); } |
818 | |
819 | /// std::hash specialization for unique_ptr. |
820 | template<typename _Tp, typename _Dp> |
821 | struct hash<unique_ptr<_Tp, _Dp>> |
822 | : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>, |
823 | private __poison_hash<typename unique_ptr<_Tp, _Dp>::pointer> |
824 | { |
825 | size_t |
826 | operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept |
827 | { |
828 | typedef unique_ptr<_Tp, _Dp> _UP; |
829 | return std::hash<typename _UP::pointer>()(__u.get()); |
830 | } |
831 | }; |
832 | |
833 | #if __cplusplus > 201103L |
834 | |
835 | #define __cpp_lib_make_unique 201304 |
836 | |
837 | template<typename _Tp> |
838 | struct _MakeUniq |
839 | { typedef unique_ptr<_Tp> __single_object; }; |
840 | |
841 | template<typename _Tp> |
842 | struct _MakeUniq<_Tp[]> |
843 | { typedef unique_ptr<_Tp[]> __array; }; |
844 | |
845 | template<typename _Tp, size_t _Bound> |
846 | struct _MakeUniq<_Tp[_Bound]> |
847 | { struct __invalid_type { }; }; |
848 | |
849 | /// std::make_unique for single objects |
850 | template<typename _Tp, typename... _Args> |
851 | inline typename _MakeUniq<_Tp>::__single_object |
852 | make_unique(_Args&&... __args) |
853 | { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); } |
854 | |
855 | /// std::make_unique for arrays of unknown bound |
856 | template<typename _Tp> |
857 | inline typename _MakeUniq<_Tp>::__array |
858 | make_unique(size_t __num) |
859 | { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); } |
860 | |
861 | /// Disable std::make_unique for arrays of known bound |
862 | template<typename _Tp, typename... _Args> |
863 | inline typename _MakeUniq<_Tp>::__invalid_type |
864 | make_unique(_Args&&...) = delete; |
865 | #endif |
866 | |
867 | // @} group pointer_abstractions |
868 | |
869 | #if __cplusplus >= 201703L |
870 | namespace __detail::__variant |
871 | { |
872 | template<typename> struct _Never_valueless_alt; // see <variant> |
873 | |
874 | // Provide the strong exception-safety guarantee when emplacing a |
875 | // unique_ptr into a variant. |
876 | template<typename _Tp, typename _Del> |
877 | struct _Never_valueless_alt<std::unique_ptr<_Tp, _Del>> |
878 | : std::true_type |
879 | { }; |
880 | } // namespace __detail::__variant |
881 | #endif // C++17 |
882 | |
883 | _GLIBCXX_END_NAMESPACE_VERSION |
884 | } // namespace |
885 | |
886 | #endif /* _UNIQUE_PTR_H */ |
887 | |