1 | // -*- C++ -*- |
2 | //===----------------------------------------------------------------------===// |
3 | // |
4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
5 | // See https://llvm.org/LICENSE.txt for license information. |
6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef _LIBCPP___MEMORY_UNIQUE_PTR_H |
11 | #define _LIBCPP___MEMORY_UNIQUE_PTR_H |
12 | |
13 | #include <__config> |
14 | #include <__functional/hash.h> |
15 | #include <__functional/operations.h> |
16 | #include <__memory/allocator_traits.h> // __pointer |
17 | #include <__memory/auto_ptr.h> |
18 | #include <__memory/compressed_pair.h> |
19 | #include <__utility/forward.h> |
20 | #include <__utility/move.h> |
21 | #include <cstddef> |
22 | #include <type_traits> |
23 | |
24 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
25 | # pragma GCC system_header |
26 | #endif |
27 | |
28 | _LIBCPP_BEGIN_NAMESPACE_STD |
29 | |
30 | template <class _Tp> |
31 | struct _LIBCPP_TEMPLATE_VIS default_delete { |
32 | static_assert(!is_function<_Tp>::value, |
33 | "default_delete cannot be instantiated for function types" ); |
34 | #ifndef _LIBCPP_CXX03_LANG |
35 | _LIBCPP_INLINE_VISIBILITY constexpr default_delete() _NOEXCEPT = default; |
36 | #else |
37 | _LIBCPP_INLINE_VISIBILITY default_delete() {} |
38 | #endif |
39 | template <class _Up> |
40 | _LIBCPP_INLINE_VISIBILITY |
41 | default_delete(const default_delete<_Up>&, |
42 | typename enable_if<is_convertible<_Up*, _Tp*>::value>::type* = |
43 | 0) _NOEXCEPT {} |
44 | |
45 | _LIBCPP_INLINE_VISIBILITY void operator()(_Tp* __ptr) const _NOEXCEPT { |
46 | static_assert(sizeof(_Tp) >= 0, "cannot delete an incomplete type" ); |
47 | static_assert(!is_void<_Tp>::value, "cannot delete an incomplete type" ); |
48 | delete __ptr; |
49 | } |
50 | }; |
51 | |
52 | template <class _Tp> |
53 | struct _LIBCPP_TEMPLATE_VIS default_delete<_Tp[]> { |
54 | private: |
55 | template <class _Up> |
56 | struct _EnableIfConvertible |
57 | : enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value> {}; |
58 | |
59 | public: |
60 | #ifndef _LIBCPP_CXX03_LANG |
61 | _LIBCPP_INLINE_VISIBILITY constexpr default_delete() _NOEXCEPT = default; |
62 | #else |
63 | _LIBCPP_INLINE_VISIBILITY default_delete() {} |
64 | #endif |
65 | |
66 | template <class _Up> |
67 | _LIBCPP_INLINE_VISIBILITY |
68 | default_delete(const default_delete<_Up[]>&, |
69 | typename _EnableIfConvertible<_Up>::type* = 0) _NOEXCEPT {} |
70 | |
71 | template <class _Up> |
72 | _LIBCPP_INLINE_VISIBILITY |
73 | typename _EnableIfConvertible<_Up>::type |
74 | operator()(_Up* __ptr) const _NOEXCEPT { |
75 | static_assert(sizeof(_Up) >= 0, "cannot delete an incomplete type" ); |
76 | delete[] __ptr; |
77 | } |
78 | }; |
79 | |
80 | template <class _Deleter> |
81 | struct __unique_ptr_deleter_sfinae { |
82 | static_assert(!is_reference<_Deleter>::value, "incorrect specialization" ); |
83 | typedef const _Deleter& __lval_ref_type; |
84 | typedef _Deleter&& __good_rval_ref_type; |
85 | typedef true_type __enable_rval_overload; |
86 | }; |
87 | |
88 | template <class _Deleter> |
89 | struct __unique_ptr_deleter_sfinae<_Deleter const&> { |
90 | typedef const _Deleter& __lval_ref_type; |
91 | typedef const _Deleter&& __bad_rval_ref_type; |
92 | typedef false_type __enable_rval_overload; |
93 | }; |
94 | |
95 | template <class _Deleter> |
96 | struct __unique_ptr_deleter_sfinae<_Deleter&> { |
97 | typedef _Deleter& __lval_ref_type; |
98 | typedef _Deleter&& __bad_rval_ref_type; |
99 | typedef false_type __enable_rval_overload; |
100 | }; |
101 | |
102 | #if defined(_LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI) |
103 | # define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI __attribute__((trivial_abi)) |
104 | #else |
105 | # define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI |
106 | #endif |
107 | |
108 | template <class _Tp, class _Dp = default_delete<_Tp> > |
109 | class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr { |
110 | public: |
111 | typedef _Tp element_type; |
112 | typedef _Dp deleter_type; |
113 | typedef _LIBCPP_NODEBUG typename __pointer<_Tp, deleter_type>::type pointer; |
114 | |
115 | static_assert(!is_rvalue_reference<deleter_type>::value, |
116 | "the specified deleter type cannot be an rvalue reference" ); |
117 | |
118 | private: |
119 | __compressed_pair<pointer, deleter_type> __ptr_; |
120 | |
121 | struct __nat { int __for_bool_; }; |
122 | |
123 | typedef _LIBCPP_NODEBUG __unique_ptr_deleter_sfinae<_Dp> _DeleterSFINAE; |
124 | |
125 | template <bool _Dummy> |
126 | using _LValRefType _LIBCPP_NODEBUG = |
127 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__lval_ref_type; |
128 | |
129 | template <bool _Dummy> |
130 | using _GoodRValRefType _LIBCPP_NODEBUG = |
131 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__good_rval_ref_type; |
132 | |
133 | template <bool _Dummy> |
134 | using _BadRValRefType _LIBCPP_NODEBUG = |
135 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__bad_rval_ref_type; |
136 | |
137 | template <bool _Dummy, class _Deleter = typename __dependent_type< |
138 | __type_identity<deleter_type>, _Dummy>::type> |
139 | using _EnableIfDeleterDefaultConstructible _LIBCPP_NODEBUG = |
140 | typename enable_if<is_default_constructible<_Deleter>::value && |
141 | !is_pointer<_Deleter>::value>::type; |
142 | |
143 | template <class _ArgType> |
144 | using _EnableIfDeleterConstructible _LIBCPP_NODEBUG = |
145 | typename enable_if<is_constructible<deleter_type, _ArgType>::value>::type; |
146 | |
147 | template <class _UPtr, class _Up> |
148 | using _EnableIfMoveConvertible _LIBCPP_NODEBUG = typename enable_if< |
149 | is_convertible<typename _UPtr::pointer, pointer>::value && |
150 | !is_array<_Up>::value |
151 | >::type; |
152 | |
153 | template <class _UDel> |
154 | using _EnableIfDeleterConvertible _LIBCPP_NODEBUG = typename enable_if< |
155 | (is_reference<_Dp>::value && is_same<_Dp, _UDel>::value) || |
156 | (!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value) |
157 | >::type; |
158 | |
159 | template <class _UDel> |
160 | using _EnableIfDeleterAssignable = typename enable_if< |
161 | is_assignable<_Dp&, _UDel&&>::value |
162 | >::type; |
163 | |
164 | public: |
165 | template <bool _Dummy = true, |
166 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > |
167 | _LIBCPP_INLINE_VISIBILITY |
168 | _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(__value_init_tag(), __value_init_tag()) {} |
169 | |
170 | template <bool _Dummy = true, |
171 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > |
172 | _LIBCPP_INLINE_VISIBILITY |
173 | _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(__value_init_tag(), __value_init_tag()) {} |
174 | |
175 | template <bool _Dummy = true, |
176 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > |
177 | _LIBCPP_INLINE_VISIBILITY |
178 | explicit unique_ptr(pointer __p) _NOEXCEPT : __ptr_(__p, __value_init_tag()) {} |
179 | |
180 | template <bool _Dummy = true, |
181 | class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > > |
182 | _LIBCPP_INLINE_VISIBILITY |
183 | unique_ptr(pointer __p, _LValRefType<_Dummy> __d) _NOEXCEPT |
184 | : __ptr_(__p, __d) {} |
185 | |
186 | template <bool _Dummy = true, |
187 | class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > > |
188 | _LIBCPP_INLINE_VISIBILITY |
189 | unique_ptr(pointer __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPT |
190 | : __ptr_(__p, _VSTD::move(__d)) { |
191 | static_assert(!is_reference<deleter_type>::value, |
192 | "rvalue deleter bound to reference" ); |
193 | } |
194 | |
195 | template <bool _Dummy = true, |
196 | class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> > > |
197 | _LIBCPP_INLINE_VISIBILITY |
198 | unique_ptr(pointer __p, _BadRValRefType<_Dummy> __d) = delete; |
199 | |
200 | _LIBCPP_INLINE_VISIBILITY |
201 | unique_ptr(unique_ptr&& __u) _NOEXCEPT |
202 | : __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) { |
203 | } |
204 | |
205 | template <class _Up, class _Ep, |
206 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, |
207 | class = _EnableIfDeleterConvertible<_Ep> |
208 | > |
209 | _LIBCPP_INLINE_VISIBILITY |
210 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT |
211 | : __ptr_(__u.release(), _VSTD::forward<_Ep>(__u.get_deleter())) {} |
212 | |
213 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) |
214 | template <class _Up> |
215 | _LIBCPP_INLINE_VISIBILITY |
216 | unique_ptr(auto_ptr<_Up>&& __p, |
217 | typename enable_if<is_convertible<_Up*, _Tp*>::value && |
218 | is_same<_Dp, default_delete<_Tp> >::value, |
219 | __nat>::type = __nat()) _NOEXCEPT |
220 | : __ptr_(__p.release(), __value_init_tag()) {} |
221 | #endif |
222 | |
223 | _LIBCPP_INLINE_VISIBILITY |
224 | unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT { |
225 | reset(p: __u.release()); |
226 | __ptr_.second() = _VSTD::forward<deleter_type>(__u.get_deleter()); |
227 | return *this; |
228 | } |
229 | |
230 | template <class _Up, class _Ep, |
231 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, |
232 | class = _EnableIfDeleterAssignable<_Ep> |
233 | > |
234 | _LIBCPP_INLINE_VISIBILITY |
235 | unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT { |
236 | reset(p: __u.release()); |
237 | __ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter()); |
238 | return *this; |
239 | } |
240 | |
241 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) |
242 | template <class _Up> |
243 | _LIBCPP_INLINE_VISIBILITY |
244 | typename enable_if<is_convertible<_Up*, _Tp*>::value && |
245 | is_same<_Dp, default_delete<_Tp> >::value, |
246 | unique_ptr&>::type |
247 | operator=(auto_ptr<_Up> __p) { |
248 | reset(__p.release()); |
249 | return *this; |
250 | } |
251 | #endif |
252 | |
253 | #ifdef _LIBCPP_CXX03_LANG |
254 | unique_ptr(unique_ptr const&) = delete; |
255 | unique_ptr& operator=(unique_ptr const&) = delete; |
256 | #endif |
257 | |
258 | _LIBCPP_INLINE_VISIBILITY |
259 | ~unique_ptr() { reset(); } |
260 | |
261 | _LIBCPP_INLINE_VISIBILITY |
262 | unique_ptr& operator=(nullptr_t) _NOEXCEPT { |
263 | reset(); |
264 | return *this; |
265 | } |
266 | |
267 | _LIBCPP_INLINE_VISIBILITY |
268 | typename add_lvalue_reference<_Tp>::type |
269 | operator*() const { |
270 | return *__ptr_.first(); |
271 | } |
272 | _LIBCPP_INLINE_VISIBILITY |
273 | pointer operator->() const _NOEXCEPT { |
274 | return __ptr_.first(); |
275 | } |
276 | _LIBCPP_INLINE_VISIBILITY |
277 | pointer get() const _NOEXCEPT { |
278 | return __ptr_.first(); |
279 | } |
280 | _LIBCPP_INLINE_VISIBILITY |
281 | deleter_type& get_deleter() _NOEXCEPT { |
282 | return __ptr_.second(); |
283 | } |
284 | _LIBCPP_INLINE_VISIBILITY |
285 | const deleter_type& get_deleter() const _NOEXCEPT { |
286 | return __ptr_.second(); |
287 | } |
288 | _LIBCPP_INLINE_VISIBILITY |
289 | explicit operator bool() const _NOEXCEPT { |
290 | return __ptr_.first() != nullptr; |
291 | } |
292 | |
293 | _LIBCPP_INLINE_VISIBILITY |
294 | pointer release() _NOEXCEPT { |
295 | pointer __t = __ptr_.first(); |
296 | __ptr_.first() = pointer(); |
297 | return __t; |
298 | } |
299 | |
300 | _LIBCPP_INLINE_VISIBILITY |
301 | void reset(pointer __p = pointer()) _NOEXCEPT { |
302 | pointer __tmp = __ptr_.first(); |
303 | __ptr_.first() = __p; |
304 | if (__tmp) |
305 | __ptr_.second()(__tmp); |
306 | } |
307 | |
308 | _LIBCPP_INLINE_VISIBILITY |
309 | void swap(unique_ptr& __u) _NOEXCEPT { |
310 | __ptr_.swap(__u.__ptr_); |
311 | } |
312 | }; |
313 | |
314 | |
315 | template <class _Tp, class _Dp> |
316 | class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp> { |
317 | public: |
318 | typedef _Tp element_type; |
319 | typedef _Dp deleter_type; |
320 | typedef typename __pointer<_Tp, deleter_type>::type pointer; |
321 | |
322 | private: |
323 | __compressed_pair<pointer, deleter_type> __ptr_; |
324 | |
325 | template <class _From> |
326 | struct _CheckArrayPointerConversion : is_same<_From, pointer> {}; |
327 | |
328 | template <class _FromElem> |
329 | struct _CheckArrayPointerConversion<_FromElem*> |
330 | : integral_constant<bool, |
331 | is_same<_FromElem*, pointer>::value || |
332 | (is_same<pointer, element_type*>::value && |
333 | is_convertible<_FromElem(*)[], element_type(*)[]>::value) |
334 | > |
335 | {}; |
336 | |
337 | typedef __unique_ptr_deleter_sfinae<_Dp> _DeleterSFINAE; |
338 | |
339 | template <bool _Dummy> |
340 | using _LValRefType _LIBCPP_NODEBUG = |
341 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__lval_ref_type; |
342 | |
343 | template <bool _Dummy> |
344 | using _GoodRValRefType _LIBCPP_NODEBUG = |
345 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__good_rval_ref_type; |
346 | |
347 | template <bool _Dummy> |
348 | using _BadRValRefType _LIBCPP_NODEBUG = |
349 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__bad_rval_ref_type; |
350 | |
351 | template <bool _Dummy, class _Deleter = typename __dependent_type< |
352 | __type_identity<deleter_type>, _Dummy>::type> |
353 | using _EnableIfDeleterDefaultConstructible _LIBCPP_NODEBUG = |
354 | typename enable_if<is_default_constructible<_Deleter>::value && |
355 | !is_pointer<_Deleter>::value>::type; |
356 | |
357 | template <class _ArgType> |
358 | using _EnableIfDeleterConstructible _LIBCPP_NODEBUG = |
359 | typename enable_if<is_constructible<deleter_type, _ArgType>::value>::type; |
360 | |
361 | template <class _Pp> |
362 | using _EnableIfPointerConvertible _LIBCPP_NODEBUG = typename enable_if< |
363 | _CheckArrayPointerConversion<_Pp>::value |
364 | >::type; |
365 | |
366 | template <class _UPtr, class _Up, |
367 | class _ElemT = typename _UPtr::element_type> |
368 | using _EnableIfMoveConvertible _LIBCPP_NODEBUG = typename enable_if< |
369 | is_array<_Up>::value && |
370 | is_same<pointer, element_type*>::value && |
371 | is_same<typename _UPtr::pointer, _ElemT*>::value && |
372 | is_convertible<_ElemT(*)[], element_type(*)[]>::value |
373 | >::type; |
374 | |
375 | template <class _UDel> |
376 | using _EnableIfDeleterConvertible _LIBCPP_NODEBUG = typename enable_if< |
377 | (is_reference<_Dp>::value && is_same<_Dp, _UDel>::value) || |
378 | (!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value) |
379 | >::type; |
380 | |
381 | template <class _UDel> |
382 | using _EnableIfDeleterAssignable _LIBCPP_NODEBUG = typename enable_if< |
383 | is_assignable<_Dp&, _UDel&&>::value |
384 | >::type; |
385 | |
386 | public: |
387 | template <bool _Dummy = true, |
388 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > |
389 | _LIBCPP_INLINE_VISIBILITY |
390 | _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(__value_init_tag(), __value_init_tag()) {} |
391 | |
392 | template <bool _Dummy = true, |
393 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > |
394 | _LIBCPP_INLINE_VISIBILITY |
395 | _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(__value_init_tag(), __value_init_tag()) {} |
396 | |
397 | template <class _Pp, bool _Dummy = true, |
398 | class = _EnableIfDeleterDefaultConstructible<_Dummy>, |
399 | class = _EnableIfPointerConvertible<_Pp> > |
400 | _LIBCPP_INLINE_VISIBILITY |
401 | explicit unique_ptr(_Pp __p) _NOEXCEPT |
402 | : __ptr_(__p, __value_init_tag()) {} |
403 | |
404 | template <class _Pp, bool _Dummy = true, |
405 | class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> >, |
406 | class = _EnableIfPointerConvertible<_Pp> > |
407 | _LIBCPP_INLINE_VISIBILITY |
408 | unique_ptr(_Pp __p, _LValRefType<_Dummy> __d) _NOEXCEPT |
409 | : __ptr_(__p, __d) {} |
410 | |
411 | template <bool _Dummy = true, |
412 | class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > > |
413 | _LIBCPP_INLINE_VISIBILITY |
414 | unique_ptr(nullptr_t, _LValRefType<_Dummy> __d) _NOEXCEPT |
415 | : __ptr_(nullptr, __d) {} |
416 | |
417 | template <class _Pp, bool _Dummy = true, |
418 | class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> >, |
419 | class = _EnableIfPointerConvertible<_Pp> > |
420 | _LIBCPP_INLINE_VISIBILITY |
421 | unique_ptr(_Pp __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPT |
422 | : __ptr_(__p, _VSTD::move(__d)) { |
423 | static_assert(!is_reference<deleter_type>::value, |
424 | "rvalue deleter bound to reference" ); |
425 | } |
426 | |
427 | template <bool _Dummy = true, |
428 | class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > > |
429 | _LIBCPP_INLINE_VISIBILITY |
430 | unique_ptr(nullptr_t, _GoodRValRefType<_Dummy> __d) _NOEXCEPT |
431 | : __ptr_(nullptr, _VSTD::move(__d)) { |
432 | static_assert(!is_reference<deleter_type>::value, |
433 | "rvalue deleter bound to reference" ); |
434 | } |
435 | |
436 | template <class _Pp, bool _Dummy = true, |
437 | class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> >, |
438 | class = _EnableIfPointerConvertible<_Pp> > |
439 | _LIBCPP_INLINE_VISIBILITY |
440 | unique_ptr(_Pp __p, _BadRValRefType<_Dummy> __d) = delete; |
441 | |
442 | _LIBCPP_INLINE_VISIBILITY |
443 | unique_ptr(unique_ptr&& __u) _NOEXCEPT |
444 | : __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) { |
445 | } |
446 | |
447 | _LIBCPP_INLINE_VISIBILITY |
448 | unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT { |
449 | reset(__u.release()); |
450 | __ptr_.second() = _VSTD::forward<deleter_type>(__u.get_deleter()); |
451 | return *this; |
452 | } |
453 | |
454 | template <class _Up, class _Ep, |
455 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, |
456 | class = _EnableIfDeleterConvertible<_Ep> |
457 | > |
458 | _LIBCPP_INLINE_VISIBILITY |
459 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT |
460 | : __ptr_(__u.release(), _VSTD::forward<_Ep>(__u.get_deleter())) { |
461 | } |
462 | |
463 | template <class _Up, class _Ep, |
464 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, |
465 | class = _EnableIfDeleterAssignable<_Ep> |
466 | > |
467 | _LIBCPP_INLINE_VISIBILITY |
468 | unique_ptr& |
469 | operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT { |
470 | reset(__u.release()); |
471 | __ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter()); |
472 | return *this; |
473 | } |
474 | |
475 | #ifdef _LIBCPP_CXX03_LANG |
476 | unique_ptr(unique_ptr const&) = delete; |
477 | unique_ptr& operator=(unique_ptr const&) = delete; |
478 | #endif |
479 | public: |
480 | _LIBCPP_INLINE_VISIBILITY |
481 | ~unique_ptr() { reset(); } |
482 | |
483 | _LIBCPP_INLINE_VISIBILITY |
484 | unique_ptr& operator=(nullptr_t) _NOEXCEPT { |
485 | reset(); |
486 | return *this; |
487 | } |
488 | |
489 | _LIBCPP_INLINE_VISIBILITY |
490 | typename add_lvalue_reference<_Tp>::type |
491 | operator[](size_t __i) const { |
492 | return __ptr_.first()[__i]; |
493 | } |
494 | _LIBCPP_INLINE_VISIBILITY |
495 | pointer get() const _NOEXCEPT { |
496 | return __ptr_.first(); |
497 | } |
498 | |
499 | _LIBCPP_INLINE_VISIBILITY |
500 | deleter_type& get_deleter() _NOEXCEPT { |
501 | return __ptr_.second(); |
502 | } |
503 | |
504 | _LIBCPP_INLINE_VISIBILITY |
505 | const deleter_type& get_deleter() const _NOEXCEPT { |
506 | return __ptr_.second(); |
507 | } |
508 | _LIBCPP_INLINE_VISIBILITY |
509 | explicit operator bool() const _NOEXCEPT { |
510 | return __ptr_.first() != nullptr; |
511 | } |
512 | |
513 | _LIBCPP_INLINE_VISIBILITY |
514 | pointer release() _NOEXCEPT { |
515 | pointer __t = __ptr_.first(); |
516 | __ptr_.first() = pointer(); |
517 | return __t; |
518 | } |
519 | |
520 | template <class _Pp> |
521 | _LIBCPP_INLINE_VISIBILITY |
522 | typename enable_if< |
523 | _CheckArrayPointerConversion<_Pp>::value |
524 | >::type |
525 | reset(_Pp __p) _NOEXCEPT { |
526 | pointer __tmp = __ptr_.first(); |
527 | __ptr_.first() = __p; |
528 | if (__tmp) |
529 | __ptr_.second()(__tmp); |
530 | } |
531 | |
532 | _LIBCPP_INLINE_VISIBILITY |
533 | void reset(nullptr_t = nullptr) _NOEXCEPT { |
534 | pointer __tmp = __ptr_.first(); |
535 | __ptr_.first() = nullptr; |
536 | if (__tmp) |
537 | __ptr_.second()(__tmp); |
538 | } |
539 | |
540 | _LIBCPP_INLINE_VISIBILITY |
541 | void swap(unique_ptr& __u) _NOEXCEPT { |
542 | __ptr_.swap(__u.__ptr_); |
543 | } |
544 | |
545 | }; |
546 | |
547 | template <class _Tp, class _Dp> |
548 | inline _LIBCPP_INLINE_VISIBILITY |
549 | typename enable_if< |
550 | __is_swappable<_Dp>::value, |
551 | void |
552 | >::type |
553 | swap(unique_ptr<_Tp, _Dp>& __x, unique_ptr<_Tp, _Dp>& __y) _NOEXCEPT {__x.swap(__y);} |
554 | |
555 | template <class _T1, class _D1, class _T2, class _D2> |
556 | inline _LIBCPP_INLINE_VISIBILITY |
557 | bool |
558 | operator==(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return __x.get() == __y.get();} |
559 | |
560 | template <class _T1, class _D1, class _T2, class _D2> |
561 | inline _LIBCPP_INLINE_VISIBILITY |
562 | bool |
563 | operator!=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__x == __y);} |
564 | |
565 | template <class _T1, class _D1, class _T2, class _D2> |
566 | inline _LIBCPP_INLINE_VISIBILITY |
567 | bool |
568 | operator< (const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) |
569 | { |
570 | typedef typename unique_ptr<_T1, _D1>::pointer _P1; |
571 | typedef typename unique_ptr<_T2, _D2>::pointer _P2; |
572 | typedef typename common_type<_P1, _P2>::type _Vp; |
573 | return less<_Vp>()(__x.get(), __y.get()); |
574 | } |
575 | |
576 | template <class _T1, class _D1, class _T2, class _D2> |
577 | inline _LIBCPP_INLINE_VISIBILITY |
578 | bool |
579 | operator> (const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return __y < __x;} |
580 | |
581 | template <class _T1, class _D1, class _T2, class _D2> |
582 | inline _LIBCPP_INLINE_VISIBILITY |
583 | bool |
584 | operator<=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__y < __x);} |
585 | |
586 | template <class _T1, class _D1, class _T2, class _D2> |
587 | inline _LIBCPP_INLINE_VISIBILITY |
588 | bool |
589 | operator>=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__x < __y);} |
590 | |
591 | template <class _T1, class _D1> |
592 | inline _LIBCPP_INLINE_VISIBILITY |
593 | bool |
594 | operator==(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPT |
595 | { |
596 | return !__x; |
597 | } |
598 | |
599 | template <class _T1, class _D1> |
600 | inline _LIBCPP_INLINE_VISIBILITY |
601 | bool |
602 | operator==(nullptr_t, const unique_ptr<_T1, _D1>& __x) _NOEXCEPT |
603 | { |
604 | return !__x; |
605 | } |
606 | |
607 | template <class _T1, class _D1> |
608 | inline _LIBCPP_INLINE_VISIBILITY |
609 | bool |
610 | operator!=(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPT |
611 | { |
612 | return static_cast<bool>(__x); |
613 | } |
614 | |
615 | template <class _T1, class _D1> |
616 | inline _LIBCPP_INLINE_VISIBILITY |
617 | bool |
618 | operator!=(nullptr_t, const unique_ptr<_T1, _D1>& __x) _NOEXCEPT |
619 | { |
620 | return static_cast<bool>(__x); |
621 | } |
622 | |
623 | template <class _T1, class _D1> |
624 | inline _LIBCPP_INLINE_VISIBILITY |
625 | bool |
626 | operator<(const unique_ptr<_T1, _D1>& __x, nullptr_t) |
627 | { |
628 | typedef typename unique_ptr<_T1, _D1>::pointer _P1; |
629 | return less<_P1>()(__x.get(), nullptr); |
630 | } |
631 | |
632 | template <class _T1, class _D1> |
633 | inline _LIBCPP_INLINE_VISIBILITY |
634 | bool |
635 | operator<(nullptr_t, const unique_ptr<_T1, _D1>& __x) |
636 | { |
637 | typedef typename unique_ptr<_T1, _D1>::pointer _P1; |
638 | return less<_P1>()(nullptr, __x.get()); |
639 | } |
640 | |
641 | template <class _T1, class _D1> |
642 | inline _LIBCPP_INLINE_VISIBILITY |
643 | bool |
644 | operator>(const unique_ptr<_T1, _D1>& __x, nullptr_t) |
645 | { |
646 | return nullptr < __x; |
647 | } |
648 | |
649 | template <class _T1, class _D1> |
650 | inline _LIBCPP_INLINE_VISIBILITY |
651 | bool |
652 | operator>(nullptr_t, const unique_ptr<_T1, _D1>& __x) |
653 | { |
654 | return __x < nullptr; |
655 | } |
656 | |
657 | template <class _T1, class _D1> |
658 | inline _LIBCPP_INLINE_VISIBILITY |
659 | bool |
660 | operator<=(const unique_ptr<_T1, _D1>& __x, nullptr_t) |
661 | { |
662 | return !(nullptr < __x); |
663 | } |
664 | |
665 | template <class _T1, class _D1> |
666 | inline _LIBCPP_INLINE_VISIBILITY |
667 | bool |
668 | operator<=(nullptr_t, const unique_ptr<_T1, _D1>& __x) |
669 | { |
670 | return !(__x < nullptr); |
671 | } |
672 | |
673 | template <class _T1, class _D1> |
674 | inline _LIBCPP_INLINE_VISIBILITY |
675 | bool |
676 | operator>=(const unique_ptr<_T1, _D1>& __x, nullptr_t) |
677 | { |
678 | return !(__x < nullptr); |
679 | } |
680 | |
681 | template <class _T1, class _D1> |
682 | inline _LIBCPP_INLINE_VISIBILITY |
683 | bool |
684 | operator>=(nullptr_t, const unique_ptr<_T1, _D1>& __x) |
685 | { |
686 | return !(nullptr < __x); |
687 | } |
688 | |
689 | #if _LIBCPP_STD_VER > 11 |
690 | |
691 | template<class _Tp> |
692 | struct __unique_if |
693 | { |
694 | typedef unique_ptr<_Tp> __unique_single; |
695 | }; |
696 | |
697 | template<class _Tp> |
698 | struct __unique_if<_Tp[]> |
699 | { |
700 | typedef unique_ptr<_Tp[]> __unique_array_unknown_bound; |
701 | }; |
702 | |
703 | template<class _Tp, size_t _Np> |
704 | struct __unique_if<_Tp[_Np]> |
705 | { |
706 | typedef void __unique_array_known_bound; |
707 | }; |
708 | |
709 | template<class _Tp, class... _Args> |
710 | inline _LIBCPP_INLINE_VISIBILITY |
711 | typename __unique_if<_Tp>::__unique_single |
712 | make_unique(_Args&&... __args) |
713 | { |
714 | return unique_ptr<_Tp>(new _Tp(_VSTD::forward<_Args>(__args)...)); |
715 | } |
716 | |
717 | template<class _Tp> |
718 | inline _LIBCPP_INLINE_VISIBILITY |
719 | typename __unique_if<_Tp>::__unique_array_unknown_bound |
720 | make_unique(size_t __n) |
721 | { |
722 | typedef typename remove_extent<_Tp>::type _Up; |
723 | return unique_ptr<_Tp>(new _Up[__n]()); |
724 | } |
725 | |
726 | template<class _Tp, class... _Args> |
727 | typename __unique_if<_Tp>::__unique_array_known_bound |
728 | make_unique(_Args&&...) = delete; |
729 | |
730 | #endif // _LIBCPP_STD_VER > 11 |
731 | |
732 | template <class _Tp> struct _LIBCPP_TEMPLATE_VIS hash; |
733 | |
734 | template <class _Tp, class _Dp> |
735 | #ifdef _LIBCPP_CXX03_LANG |
736 | struct _LIBCPP_TEMPLATE_VIS hash<unique_ptr<_Tp, _Dp> > |
737 | #else |
738 | struct _LIBCPP_TEMPLATE_VIS hash<__enable_hash_helper< |
739 | unique_ptr<_Tp, _Dp>, typename unique_ptr<_Tp, _Dp>::pointer> > |
740 | #endif |
741 | { |
742 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) |
743 | _LIBCPP_DEPRECATED_IN_CXX17 typedef unique_ptr<_Tp, _Dp> argument_type; |
744 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; |
745 | #endif |
746 | |
747 | _LIBCPP_INLINE_VISIBILITY |
748 | size_t operator()(const unique_ptr<_Tp, _Dp>& __ptr) const |
749 | { |
750 | typedef typename unique_ptr<_Tp, _Dp>::pointer pointer; |
751 | return hash<pointer>()(__ptr.get()); |
752 | } |
753 | }; |
754 | |
755 | _LIBCPP_END_NAMESPACE_STD |
756 | |
757 | #endif // _LIBCPP___MEMORY_UNIQUE_PTR_H |
758 | |