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 |
11 | #define _LIBCPP_MEMORY |
12 | |
13 | /* |
14 | memory synopsis |
15 | |
16 | namespace std |
17 | { |
18 | |
19 | struct allocator_arg_t { }; |
20 | inline constexpr allocator_arg_t allocator_arg = allocator_arg_t(); |
21 | |
22 | template <class T, class Alloc> struct uses_allocator; |
23 | |
24 | template <class Ptr> |
25 | struct pointer_traits |
26 | { |
27 | typedef Ptr pointer; |
28 | typedef <details> element_type; |
29 | typedef <details> difference_type; |
30 | |
31 | template <class U> using rebind = <details>; |
32 | |
33 | static pointer pointer_to(<details>); |
34 | }; |
35 | |
36 | template <class T> |
37 | struct pointer_traits<T*> |
38 | { |
39 | typedef T* pointer; |
40 | typedef T element_type; |
41 | typedef ptrdiff_t difference_type; |
42 | |
43 | template <class U> using rebind = U*; |
44 | |
45 | static pointer pointer_to(<details>) noexcept; // constexpr in C++20 |
46 | }; |
47 | |
48 | template <class T> constexpr T* to_address(T* p) noexcept; // C++20 |
49 | template <class Ptr> constexpr auto to_address(const Ptr& p) noexcept; // C++20 |
50 | |
51 | template <class Alloc> |
52 | struct allocator_traits |
53 | { |
54 | typedef Alloc allocator_type; |
55 | typedef typename allocator_type::value_type |
56 | value_type; |
57 | |
58 | typedef Alloc::pointer | value_type* pointer; |
59 | typedef Alloc::const_pointer |
60 | | pointer_traits<pointer>::rebind<const value_type> |
61 | const_pointer; |
62 | typedef Alloc::void_pointer |
63 | | pointer_traits<pointer>::rebind<void> |
64 | void_pointer; |
65 | typedef Alloc::const_void_pointer |
66 | | pointer_traits<pointer>::rebind<const void> |
67 | const_void_pointer; |
68 | typedef Alloc::difference_type |
69 | | pointer_traits<pointer>::difference_type |
70 | difference_type; |
71 | typedef Alloc::size_type |
72 | | make_unsigned<difference_type>::type |
73 | size_type; |
74 | typedef Alloc::propagate_on_container_copy_assignment |
75 | | false_type propagate_on_container_copy_assignment; |
76 | typedef Alloc::propagate_on_container_move_assignment |
77 | | false_type propagate_on_container_move_assignment; |
78 | typedef Alloc::propagate_on_container_swap |
79 | | false_type propagate_on_container_swap; |
80 | typedef Alloc::is_always_equal |
81 | | is_empty is_always_equal; |
82 | |
83 | template <class T> using rebind_alloc = Alloc::rebind<T>::other | Alloc<T, Args...>; |
84 | template <class T> using rebind_traits = allocator_traits<rebind_alloc<T>>; |
85 | |
86 | static pointer allocate(allocator_type& a, size_type n); // constexpr and [[nodiscard]] in C++20 |
87 | static pointer allocate(allocator_type& a, size_type n, const_void_pointer hint); // constexpr and [[nodiscard]] in C++20 |
88 | |
89 | static void deallocate(allocator_type& a, pointer p, size_type n) noexcept; // constexpr in C++20 |
90 | |
91 | template <class T, class... Args> |
92 | static void construct(allocator_type& a, T* p, Args&&... args); // constexpr in C++20 |
93 | |
94 | template <class T> |
95 | static void destroy(allocator_type& a, T* p); // constexpr in C++20 |
96 | |
97 | static size_type max_size(const allocator_type& a); // noexcept in C++14, constexpr in C++20 |
98 | static allocator_type select_on_container_copy_construction(const allocator_type& a); // constexpr in C++20 |
99 | }; |
100 | |
101 | template<class Pointer> |
102 | struct allocation_result { |
103 | Pointer ptr; |
104 | size_t count; |
105 | }; // since C++23 |
106 | |
107 | template<class Allocator> |
108 | [[nodiscard]] constexpr allocation_result<typename allocator_traits<Allocator>::pointer> |
109 | allocate_at_least(Allocator& a, size_t n); // since C++23 |
110 | |
111 | template <> |
112 | class allocator<void> // removed in C++20 |
113 | { |
114 | public: |
115 | typedef void* pointer; |
116 | typedef const void* const_pointer; |
117 | typedef void value_type; |
118 | |
119 | template <class _Up> struct rebind {typedef allocator<_Up> other;}; |
120 | }; |
121 | |
122 | template <class T> |
123 | class allocator |
124 | { |
125 | public: |
126 | typedef size_t size_type; |
127 | typedef ptrdiff_t difference_type; |
128 | typedef T* pointer; // deprecated in C++17, removed in C++20 |
129 | typedef const T* const_pointer; // deprecated in C++17, removed in C++20 |
130 | typedef typename add_lvalue_reference<T>::type |
131 | reference; // deprecated in C++17, removed in C++20 |
132 | typedef typename add_lvalue_reference<const T>::type |
133 | const_reference; // deprecated in C++17, removed in C++20 |
134 | |
135 | typedef T value_type; |
136 | |
137 | template <class U> struct rebind {typedef allocator<U> other;}; // deprecated in C++17, removed in C++20 |
138 | |
139 | typedef true_type propagate_on_container_move_assignment; |
140 | typedef true_type is_always_equal; |
141 | |
142 | constexpr allocator() noexcept; // constexpr in C++20 |
143 | constexpr allocator(const allocator&) noexcept; // constexpr in C++20 |
144 | template <class U> |
145 | constexpr allocator(const allocator<U>&) noexcept; // constexpr in C++20 |
146 | ~allocator(); // constexpr in C++20 |
147 | pointer address(reference x) const noexcept; // deprecated in C++17, removed in C++20 |
148 | const_pointer address(const_reference x) const noexcept; // deprecated in C++17, removed in C++20 |
149 | T* allocate(size_t n, const void* hint); // deprecated in C++17, removed in C++20 |
150 | T* allocate(size_t n); // constexpr in C++20 |
151 | void deallocate(T* p, size_t n) noexcept; // constexpr in C++20 |
152 | size_type max_size() const noexcept; // deprecated in C++17, removed in C++20 |
153 | template<class U, class... Args> |
154 | void construct(U* p, Args&&... args); // deprecated in C++17, removed in C++20 |
155 | template <class U> |
156 | void destroy(U* p); // deprecated in C++17, removed in C++20 |
157 | }; |
158 | |
159 | template <class T, class U> |
160 | bool operator==(const allocator<T>&, const allocator<U>&) noexcept; // constexpr in C++20 |
161 | |
162 | template <class T, class U> |
163 | bool operator!=(const allocator<T>&, const allocator<U>&) noexcept; // constexpr in C++20 |
164 | |
165 | template <class OutputIterator, class T> |
166 | class raw_storage_iterator // deprecated in C++17, removed in C++20 |
167 | : public iterator<output_iterator_tag, void, void, void, void> // until C++17 |
168 | { |
169 | public: |
170 | typedef output_iterator_tag iterator_category; |
171 | typedef void value_type; |
172 | typedef void difference_type; // until C++20 |
173 | typedef ptrdiff_t difference_type; // since C++20 |
174 | typedef void pointer; |
175 | typedef void reference; |
176 | |
177 | explicit raw_storage_iterator(OutputIterator x); |
178 | raw_storage_iterator& operator*(); |
179 | raw_storage_iterator& operator=(const T& element); |
180 | raw_storage_iterator& operator++(); |
181 | raw_storage_iterator operator++(int); |
182 | }; |
183 | |
184 | template <class T> pair<T*,ptrdiff_t> get_temporary_buffer(ptrdiff_t n) noexcept; |
185 | template <class T> void return_temporary_buffer(T* p) noexcept; |
186 | |
187 | template <class T> T* addressof(T& r) noexcept; |
188 | template <class T> T* addressof(const T&& r) noexcept = delete; |
189 | |
190 | template <class InputIterator, class ForwardIterator> |
191 | ForwardIterator |
192 | uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result); |
193 | |
194 | namespace ranges { |
195 | |
196 | template<class InputIterator, class OutputIterator> |
197 | using uninitialized_copy_result = in_out_result<InputIterator, OutputIterator>; // since C++20 |
198 | |
199 | template<input_iterator InputIterator, sentinel-for<InputIterator> Sentinel1, nothrow-forward-iterator OutputIterator, nothrow-sentinel-for<OutputIterator> Sentinel2> |
200 | requires constructible_from<iter_value_t<OutputIterator>, iter_reference_t<InputIterator>> |
201 | uninitialized_copy_result<InputIterator, OutputIterator> |
202 | uninitialized_copy(InputIterator ifirst, Sentinel1 ilast, OutputIterator ofirst, Sentinel2 olast); // since C++20 |
203 | |
204 | template<input_range InputRange, nothrow-forward-range OutputRange> |
205 | requires constructible_from<range_value_t<OutputRange>, range_reference_t<InputRange>> |
206 | uninitialized_copy_result<borrowed_iterator_t<InputRange>, borrowed_iterator_t<OutputRange>> |
207 | uninitialized_copy(InputRange&& in_range, OutputRange&& out_range); // since C++20 |
208 | |
209 | } |
210 | |
211 | template <class InputIterator, class Size, class ForwardIterator> |
212 | ForwardIterator |
213 | uninitialized_copy_n(InputIterator first, Size n, ForwardIterator result); |
214 | |
215 | namespace ranges { |
216 | |
217 | template<class InputIterator, class OutputIterator> |
218 | using uninitialized_copy_n_result = in_out_result<InputIterator, OutputIterator>; // since C++20 |
219 | |
220 | template<input_iterator InputIterator, nothrow-forward-iterator OutputIterator, nothrow-sentinel-for<OutputIterator> Sentinel> |
221 | requires constructible_from<iter_value_t<OutputIterator>, iter_reference_t<InputIterator>> |
222 | uninitialized_copy_n_result<InputIterator, OutputIterator> |
223 | uninitialized_copy_n(InputIterator ifirst, iter_difference_t<InputIterator> n, OutputIterator ofirst, Sentinel olast); // since C++20 |
224 | |
225 | } |
226 | |
227 | template <class ForwardIterator, class T> |
228 | void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& x); |
229 | |
230 | namespace ranges { |
231 | |
232 | template <nothrow-forward-iterator ForwardIterator, nothrow-sentinel-for<ForwardIterator> Sentinel, class T> |
233 | requires constructible_from<iter_value_t<ForwardIterator>, const T&> |
234 | ForwardIterator uninitialized_fill(ForwardIterator first, Sentinel last, const T& x); // since C++20 |
235 | |
236 | template <nothrow-forward-range ForwardRange, class T> |
237 | requires constructible_from<range_value_t<ForwardRange>, const T&> |
238 | borrowed_iterator_t<ForwardRange> uninitialized_fill(ForwardRange&& range, const T& x); // since C++20 |
239 | |
240 | } |
241 | |
242 | template <class ForwardIterator, class Size, class T> |
243 | ForwardIterator |
244 | uninitialized_fill_n(ForwardIterator first, Size n, const T& x); |
245 | |
246 | namespace ranges { |
247 | |
248 | template <nothrow-forward-iterator ForwardIterator, class T> |
249 | requires constructible_from<iter_value_t<ForwardIterator>, const T&> |
250 | ForwardIterator uninitialized_fill_n(ForwardIterator first, iter_difference_t<ForwardIterator> n); // since C++20 |
251 | |
252 | } |
253 | |
254 | template <class T, class ...Args> |
255 | constexpr T* construct_at(T* location, Args&& ...args); // since C++20 |
256 | |
257 | namespace ranges { |
258 | template<class T, class... Args> |
259 | constexpr T* construct_at(T* location, Args&&... args); // since C++20 |
260 | } |
261 | |
262 | template <class T> |
263 | void destroy_at(T* location); // constexpr in C++20 |
264 | |
265 | namespace ranges { |
266 | template<destructible T> |
267 | constexpr void destroy_at(T* location) noexcept; // since C++20 |
268 | } |
269 | |
270 | template <class ForwardIterator> |
271 | void destroy(ForwardIterator first, ForwardIterator last); // constexpr in C++20 |
272 | |
273 | namespace ranges { |
274 | template<nothrow-input-iterator InputIterator, nothrow-sentinel-for<InputIterator> Sentinel> |
275 | requires destructible<iter_value_t<InputIterator>> |
276 | constexpr InputIterator destroy(InputIterator first, Sentinel last) noexcept; // since C++20 |
277 | template<nothrow-input-range InputRange> |
278 | requires destructible<range_value_t<InputRange>> |
279 | constexpr borrowed_iterator_t<InputRange> destroy(InputRange&& range) noexcept; // since C++20 |
280 | } |
281 | |
282 | template <class ForwardIterator, class Size> |
283 | ForwardIterator destroy_n(ForwardIterator first, Size n); // constexpr in C++20 |
284 | |
285 | namespace ranges { |
286 | template<nothrow-input-iterator InputIterator> |
287 | requires destructible<iter_value_t<InputIterator>> |
288 | constexpr InputIterator destroy_n(InputIterator first, iter_difference_t<InputIterator> n) noexcept; // since C++20 |
289 | } |
290 | |
291 | template <class InputIterator, class ForwardIterator> |
292 | ForwardIterator uninitialized_move(InputIterator first, InputIterator last, ForwardIterator result); |
293 | |
294 | namespace ranges { |
295 | |
296 | template<class InputIterator, class OutputIterator> |
297 | using uninitialized_move_result = in_out_result<InputIterator, OutputIterator>; // since C++20 |
298 | |
299 | template <input_iterator InputIterator, sentinel_for<InputIterator> Sentinel1, nothrow-forward-iterator OutputIterator, nothrow-sentinel-for<O> Sentinel2> |
300 | requires constructible_from<iter_value_t<OutputIterator>, iter_rvalue_reference_t<InputIterator>> |
301 | uninitialized_move_result<InputIterator, OutputIterator> |
302 | uninitialized_move(InputIterator ifirst, Sentinel1 ilast, OutputIterator ofirst, Sentinel2 olast); // since C++20 |
303 | |
304 | template<input_range InputRange, nothrow-forward-range OutputRange> |
305 | requires constructible_from<range_value_t<OutputRange>, range_rvalue_reference_t<InputRange>> |
306 | uninitialized_move_result<borrowed_iterator_t<InputRange>, borrowed_iterator_t<OutputRange>> |
307 | uninitialized_move(InputRange&& in_range, OutputRange&& out_range); // since C++20 |
308 | |
309 | } |
310 | |
311 | template <class InputIterator, class Size, class ForwardIterator> |
312 | pair<InputIterator,ForwardIterator> uninitialized_move_n(InputIterator first, Size n, ForwardIterator result); |
313 | |
314 | namespace ranges { |
315 | |
316 | template<class InputIterator, class OutputIterator> |
317 | using uninitialized_move_n_result = in_out_result<InputIterator, OutputIterator>; // since C++20 |
318 | |
319 | template<input_iterator InputIterator, nothrow-forward-iterator OutputIterator, nothrow-sentinel-for<OutputIterator> Sentinel> |
320 | requires constructible_from<iter_value_t<OutputIterator>, iter_rvalue_reference_t<InputIterator>> |
321 | uninitialized_move_n_result<InputIterator, OutputIterator> |
322 | uninitialized_move_n(InputIterator ifirst, iter_difference_t<InputIterator> n, OutputIterator ofirst, Sentinel olast); // since C++20 |
323 | |
324 | } |
325 | |
326 | template <class ForwardIterator> |
327 | void uninitialized_value_construct(ForwardIterator first, ForwardIterator last); |
328 | |
329 | namespace ranges { |
330 | |
331 | template <nothrow-forward-iterator ForwardIterator, nothrow-sentinel-for<ForwardIterator> Sentinel> |
332 | requires default_initializable<iter_value_t<ForwardIterator>> |
333 | ForwardIterator uninitialized_value_construct(ForwardIterator first, Sentinel last); // since C++20 |
334 | |
335 | template <nothrow-forward-range ForwardRange> |
336 | requires default_initializable<range_value_t<ForwardRange>> |
337 | borrowed_iterator_t<ForwardRange> uninitialized_value_construct(ForwardRange&& r); // since C++20 |
338 | |
339 | } |
340 | |
341 | template <class ForwardIterator, class Size> |
342 | ForwardIterator uninitialized_value_construct_n(ForwardIterator first, Size n); |
343 | |
344 | namespace ranges { |
345 | |
346 | template <nothrow-forward-iterator ForwardIterator> |
347 | requires default_initializable<iter_value_t<ForwardIterator>> |
348 | ForwardIterator uninitialized_value_construct_n(ForwardIterator first, iter_difference_t<ForwardIterator> n); // since C++20 |
349 | |
350 | } |
351 | |
352 | template <class ForwardIterator> |
353 | void uninitialized_default_construct(ForwardIterator first, ForwardIterator last); |
354 | |
355 | namespace ranges { |
356 | |
357 | template <nothrow-forward-iterator ForwardIterator, nothrow-sentinel-for<ForwardIterator> Sentinel> |
358 | requires default_initializable<iter_value_t<ForwardIterator>> |
359 | ForwardIterator uninitialized_default_construct(ForwardIterator first, Sentinel last); // since C++20 |
360 | |
361 | template <nothrow-forward-range ForwardRange> |
362 | requires default_initializable<range_value_t<ForwardRange>> |
363 | borrowed_iterator_t<ForwardRange> uninitialized_default_construct(ForwardRange&& r); // since C++20 |
364 | |
365 | } |
366 | |
367 | template <class ForwardIterator, class Size> |
368 | ForwardIterator uninitialized_default_construct_n(ForwardIterator first, Size n); |
369 | |
370 | namespace ranges { |
371 | |
372 | template <nothrow-forward-iterator ForwardIterator> |
373 | requires default_initializable<iter_value_t<ForwardIterator>> |
374 | ForwardIterator uninitialized_default_construct_n(ForwardIterator first, iter_difference_t<ForwardIterator> n); // since C++20 |
375 | |
376 | } |
377 | |
378 | template <class Y> struct auto_ptr_ref {}; // deprecated in C++11, removed in C++17 |
379 | |
380 | template<class X> |
381 | class auto_ptr // deprecated in C++11, removed in C++17 |
382 | { |
383 | public: |
384 | typedef X element_type; |
385 | |
386 | explicit auto_ptr(X* p =0) throw(); |
387 | auto_ptr(auto_ptr&) throw(); |
388 | template<class Y> auto_ptr(auto_ptr<Y>&) throw(); |
389 | auto_ptr& operator=(auto_ptr&) throw(); |
390 | template<class Y> auto_ptr& operator=(auto_ptr<Y>&) throw(); |
391 | auto_ptr& operator=(auto_ptr_ref<X> r) throw(); |
392 | ~auto_ptr() throw(); |
393 | |
394 | typename add_lvalue_reference<X>::type operator*() const throw(); |
395 | X* operator->() const throw(); |
396 | X* get() const throw(); |
397 | X* release() throw(); |
398 | void reset(X* p =0) throw(); |
399 | |
400 | auto_ptr(auto_ptr_ref<X>) throw(); |
401 | template<class Y> operator auto_ptr_ref<Y>() throw(); |
402 | template<class Y> operator auto_ptr<Y>() throw(); |
403 | }; |
404 | |
405 | template <class T> |
406 | struct default_delete |
407 | { |
408 | constexpr default_delete() noexcept = default; |
409 | template <class U> default_delete(const default_delete<U>&) noexcept; |
410 | |
411 | void operator()(T*) const noexcept; |
412 | }; |
413 | |
414 | template <class T> |
415 | struct default_delete<T[]> |
416 | { |
417 | constexpr default_delete() noexcept = default; |
418 | void operator()(T*) const noexcept; |
419 | template <class U> void operator()(U*) const = delete; |
420 | }; |
421 | |
422 | template <class T, class D = default_delete<T>> |
423 | class unique_ptr |
424 | { |
425 | public: |
426 | typedef see below pointer; |
427 | typedef T element_type; |
428 | typedef D deleter_type; |
429 | |
430 | // constructors |
431 | constexpr unique_ptr() noexcept; |
432 | explicit unique_ptr(pointer p) noexcept; |
433 | unique_ptr(pointer p, see below d1) noexcept; |
434 | unique_ptr(pointer p, see below d2) noexcept; |
435 | unique_ptr(unique_ptr&& u) noexcept; |
436 | unique_ptr(nullptr_t) noexcept : unique_ptr() { } |
437 | template <class U, class E> |
438 | unique_ptr(unique_ptr<U, E>&& u) noexcept; |
439 | template <class U> |
440 | unique_ptr(auto_ptr<U>&& u) noexcept; // removed in C++17 |
441 | |
442 | // destructor |
443 | ~unique_ptr(); |
444 | |
445 | // assignment |
446 | unique_ptr& operator=(unique_ptr&& u) noexcept; |
447 | template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept; |
448 | unique_ptr& operator=(nullptr_t) noexcept; |
449 | |
450 | // observers |
451 | typename add_lvalue_reference<T>::type operator*() const; |
452 | pointer operator->() const noexcept; |
453 | pointer get() const noexcept; |
454 | deleter_type& get_deleter() noexcept; |
455 | const deleter_type& get_deleter() const noexcept; |
456 | explicit operator bool() const noexcept; |
457 | |
458 | // modifiers |
459 | pointer release() noexcept; |
460 | void reset(pointer p = pointer()) noexcept; |
461 | void swap(unique_ptr& u) noexcept; |
462 | }; |
463 | |
464 | template <class T, class D> |
465 | class unique_ptr<T[], D> |
466 | { |
467 | public: |
468 | typedef implementation-defined pointer; |
469 | typedef T element_type; |
470 | typedef D deleter_type; |
471 | |
472 | // constructors |
473 | constexpr unique_ptr() noexcept; |
474 | explicit unique_ptr(pointer p) noexcept; |
475 | unique_ptr(pointer p, see below d) noexcept; |
476 | unique_ptr(pointer p, see below d) noexcept; |
477 | unique_ptr(unique_ptr&& u) noexcept; |
478 | unique_ptr(nullptr_t) noexcept : unique_ptr() { } |
479 | |
480 | // destructor |
481 | ~unique_ptr(); |
482 | |
483 | // assignment |
484 | unique_ptr& operator=(unique_ptr&& u) noexcept; |
485 | unique_ptr& operator=(nullptr_t) noexcept; |
486 | |
487 | // observers |
488 | T& operator[](size_t i) const; |
489 | pointer get() const noexcept; |
490 | deleter_type& get_deleter() noexcept; |
491 | const deleter_type& get_deleter() const noexcept; |
492 | explicit operator bool() const noexcept; |
493 | |
494 | // modifiers |
495 | pointer release() noexcept; |
496 | void reset(pointer p = pointer()) noexcept; |
497 | void reset(nullptr_t) noexcept; |
498 | template <class U> void reset(U) = delete; |
499 | void swap(unique_ptr& u) noexcept; |
500 | }; |
501 | |
502 | template <class T, class D> |
503 | void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept; |
504 | |
505 | template <class T1, class D1, class T2, class D2> |
506 | bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); |
507 | template <class T1, class D1, class T2, class D2> |
508 | bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); |
509 | template <class T1, class D1, class T2, class D2> |
510 | bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); |
511 | template <class T1, class D1, class T2, class D2> |
512 | bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); |
513 | template <class T1, class D1, class T2, class D2> |
514 | bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); |
515 | template <class T1, class D1, class T2, class D2> |
516 | bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); |
517 | |
518 | template <class T, class D> |
519 | bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept; |
520 | template <class T, class D> |
521 | bool operator==(nullptr_t, const unique_ptr<T, D>& y) noexcept; |
522 | template <class T, class D> |
523 | bool operator!=(const unique_ptr<T, D>& x, nullptr_t) noexcept; |
524 | template <class T, class D> |
525 | bool operator!=(nullptr_t, const unique_ptr<T, D>& y) noexcept; |
526 | |
527 | template <class T, class D> |
528 | bool operator<(const unique_ptr<T, D>& x, nullptr_t); |
529 | template <class T, class D> |
530 | bool operator<(nullptr_t, const unique_ptr<T, D>& y); |
531 | template <class T, class D> |
532 | bool operator<=(const unique_ptr<T, D>& x, nullptr_t); |
533 | template <class T, class D> |
534 | bool operator<=(nullptr_t, const unique_ptr<T, D>& y); |
535 | template <class T, class D> |
536 | bool operator>(const unique_ptr<T, D>& x, nullptr_t); |
537 | template <class T, class D> |
538 | bool operator>(nullptr_t, const unique_ptr<T, D>& y); |
539 | template <class T, class D> |
540 | bool operator>=(const unique_ptr<T, D>& x, nullptr_t); |
541 | template <class T, class D> |
542 | bool operator>=(nullptr_t, const unique_ptr<T, D>& y); |
543 | |
544 | class bad_weak_ptr |
545 | : public std::exception |
546 | { |
547 | bad_weak_ptr() noexcept; |
548 | }; |
549 | |
550 | template<class T, class... Args> unique_ptr<T> make_unique(Args&&... args); // C++14 |
551 | template<class T> unique_ptr<T> make_unique(size_t n); // C++14 |
552 | template<class T, class... Args> unspecified make_unique(Args&&...) = delete; // C++14, T == U[N] |
553 | |
554 | template<class E, class T, class Y, class D> |
555 | basic_ostream<E, T>& operator<< (basic_ostream<E, T>& os, unique_ptr<Y, D> const& p); |
556 | |
557 | template<class T> |
558 | class shared_ptr |
559 | { |
560 | public: |
561 | typedef T element_type; // until C++17 |
562 | typedef remove_extent_t<T> element_type; // since C++17 |
563 | typedef weak_ptr<T> weak_type; // C++17 |
564 | |
565 | // constructors: |
566 | constexpr shared_ptr() noexcept; |
567 | template<class Y> explicit shared_ptr(Y* p); |
568 | template<class Y, class D> shared_ptr(Y* p, D d); |
569 | template<class Y, class D, class A> shared_ptr(Y* p, D d, A a); |
570 | template <class D> shared_ptr(nullptr_t p, D d); |
571 | template <class D, class A> shared_ptr(nullptr_t p, D d, A a); |
572 | template<class Y> shared_ptr(const shared_ptr<Y>& r, T *p) noexcept; |
573 | shared_ptr(const shared_ptr& r) noexcept; |
574 | template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept; |
575 | shared_ptr(shared_ptr&& r) noexcept; |
576 | template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept; |
577 | template<class Y> explicit shared_ptr(const weak_ptr<Y>& r); |
578 | template<class Y> shared_ptr(auto_ptr<Y>&& r); // removed in C++17 |
579 | template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r); |
580 | shared_ptr(nullptr_t) : shared_ptr() { } |
581 | |
582 | // destructor: |
583 | ~shared_ptr(); |
584 | |
585 | // assignment: |
586 | shared_ptr& operator=(const shared_ptr& r) noexcept; |
587 | template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) noexcept; |
588 | shared_ptr& operator=(shared_ptr&& r) noexcept; |
589 | template<class Y> shared_ptr& operator=(shared_ptr<Y>&& r); |
590 | template<class Y> shared_ptr& operator=(auto_ptr<Y>&& r); // removed in C++17 |
591 | template <class Y, class D> shared_ptr& operator=(unique_ptr<Y, D>&& r); |
592 | |
593 | // modifiers: |
594 | void swap(shared_ptr& r) noexcept; |
595 | void reset() noexcept; |
596 | template<class Y> void reset(Y* p); |
597 | template<class Y, class D> void reset(Y* p, D d); |
598 | template<class Y, class D, class A> void reset(Y* p, D d, A a); |
599 | |
600 | // observers: |
601 | T* get() const noexcept; |
602 | T& operator*() const noexcept; |
603 | T* operator->() const noexcept; |
604 | long use_count() const noexcept; |
605 | bool unique() const noexcept; |
606 | explicit operator bool() const noexcept; |
607 | template<class U> bool owner_before(shared_ptr<U> const& b) const noexcept; |
608 | template<class U> bool owner_before(weak_ptr<U> const& b) const noexcept; |
609 | }; |
610 | |
611 | template<class T> |
612 | shared_ptr(weak_ptr<T>) -> shared_ptr<T>; |
613 | template<class T, class D> |
614 | shared_ptr(unique_ptr<T, D>) -> shared_ptr<T>; |
615 | |
616 | // shared_ptr comparisons: |
617 | template<class T, class U> |
618 | bool operator==(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept; |
619 | template<class T, class U> |
620 | bool operator!=(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept; |
621 | template<class T, class U> |
622 | bool operator<(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept; |
623 | template<class T, class U> |
624 | bool operator>(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept; |
625 | template<class T, class U> |
626 | bool operator<=(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept; |
627 | template<class T, class U> |
628 | bool operator>=(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept; |
629 | |
630 | template <class T> |
631 | bool operator==(const shared_ptr<T>& x, nullptr_t) noexcept; |
632 | template <class T> |
633 | bool operator==(nullptr_t, const shared_ptr<T>& y) noexcept; |
634 | template <class T> |
635 | bool operator!=(const shared_ptr<T>& x, nullptr_t) noexcept; |
636 | template <class T> |
637 | bool operator!=(nullptr_t, const shared_ptr<T>& y) noexcept; |
638 | template <class T> |
639 | bool operator<(const shared_ptr<T>& x, nullptr_t) noexcept; |
640 | template <class T> |
641 | bool operator<(nullptr_t, const shared_ptr<T>& y) noexcept; |
642 | template <class T> |
643 | bool operator<=(const shared_ptr<T>& x, nullptr_t) noexcept; |
644 | template <class T> |
645 | bool operator<=(nullptr_t, const shared_ptr<T>& y) noexcept; |
646 | template <class T> |
647 | bool operator>(const shared_ptr<T>& x, nullptr_t) noexcept; |
648 | template <class T> |
649 | bool operator>(nullptr_t, const shared_ptr<T>& y) noexcept; |
650 | template <class T> |
651 | bool operator>=(const shared_ptr<T>& x, nullptr_t) noexcept; |
652 | template <class T> |
653 | bool operator>=(nullptr_t, const shared_ptr<T>& y) noexcept; |
654 | |
655 | // shared_ptr specialized algorithms: |
656 | template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept; |
657 | |
658 | // shared_ptr casts: |
659 | template<class T, class U> |
660 | shared_ptr<T> static_pointer_cast(shared_ptr<U> const& r) noexcept; |
661 | template<class T, class U> |
662 | shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const& r) noexcept; |
663 | template<class T, class U> |
664 | shared_ptr<T> const_pointer_cast(shared_ptr<U> const& r) noexcept; |
665 | |
666 | // shared_ptr I/O: |
667 | template<class E, class T, class Y> |
668 | basic_ostream<E, T>& operator<< (basic_ostream<E, T>& os, shared_ptr<Y> const& p); |
669 | |
670 | // shared_ptr get_deleter: |
671 | template<class D, class T> D* get_deleter(shared_ptr<T> const& p) noexcept; |
672 | |
673 | template<class T, class... Args> |
674 | shared_ptr<T> make_shared(Args&&... args); // T is not an array |
675 | template<class T, class A, class... Args> |
676 | shared_ptr<T> allocate_shared(const A& a, Args&&... args); // T is not an array |
677 | |
678 | template<class T> |
679 | shared_ptr<T> make_shared(size_t N); // T is U[] (since C++20) |
680 | template<class T, class A> |
681 | shared_ptr<T> allocate_shared(const A& a, size_t N); // T is U[] (since C++20) |
682 | |
683 | template<class T> |
684 | shared_ptr<T> make_shared(); // T is U[N] (since C++20) |
685 | template<class T, class A> |
686 | shared_ptr<T> allocate_shared(const A& a); // T is U[N] (since C++20) |
687 | |
688 | template<class T> |
689 | shared_ptr<T> make_shared(size_t N, const remove_extent_t<T>& u); // T is U[] (since C++20) |
690 | template<class T, class A> |
691 | shared_ptr<T> allocate_shared(const A& a, size_t N, const remove_extent_t<T>& u); // T is U[] (since C++20) |
692 | |
693 | template<class T> shared_ptr<T> |
694 | make_shared(const remove_extent_t<T>& u); // T is U[N] (since C++20) |
695 | template<class T, class A> |
696 | shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& u); // T is U[N] (since C++20) |
697 | |
698 | template<class T> |
699 | class weak_ptr |
700 | { |
701 | public: |
702 | typedef T element_type; // until C++17 |
703 | typedef remove_extent_t<T> element_type; // since C++17 |
704 | |
705 | // constructors |
706 | constexpr weak_ptr() noexcept; |
707 | template<class Y> weak_ptr(shared_ptr<Y> const& r) noexcept; |
708 | weak_ptr(weak_ptr const& r) noexcept; |
709 | template<class Y> weak_ptr(weak_ptr<Y> const& r) noexcept; |
710 | weak_ptr(weak_ptr&& r) noexcept; // C++14 |
711 | template<class Y> weak_ptr(weak_ptr<Y>&& r) noexcept; // C++14 |
712 | |
713 | // destructor |
714 | ~weak_ptr(); |
715 | |
716 | // assignment |
717 | weak_ptr& operator=(weak_ptr const& r) noexcept; |
718 | template<class Y> weak_ptr& operator=(weak_ptr<Y> const& r) noexcept; |
719 | template<class Y> weak_ptr& operator=(shared_ptr<Y> const& r) noexcept; |
720 | weak_ptr& operator=(weak_ptr&& r) noexcept; // C++14 |
721 | template<class Y> weak_ptr& operator=(weak_ptr<Y>&& r) noexcept; // C++14 |
722 | |
723 | // modifiers |
724 | void swap(weak_ptr& r) noexcept; |
725 | void reset() noexcept; |
726 | |
727 | // observers |
728 | long use_count() const noexcept; |
729 | bool expired() const noexcept; |
730 | shared_ptr<T> lock() const noexcept; |
731 | template<class U> bool owner_before(shared_ptr<U> const& b) const noexcept; |
732 | template<class U> bool owner_before(weak_ptr<U> const& b) const noexcept; |
733 | }; |
734 | |
735 | template<class T> |
736 | weak_ptr(shared_ptr<T>) -> weak_ptr<T>; |
737 | |
738 | // weak_ptr specialized algorithms: |
739 | template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept; |
740 | |
741 | // class owner_less: |
742 | template<class T> struct owner_less; |
743 | |
744 | template<class T> |
745 | struct owner_less<shared_ptr<T> > |
746 | : binary_function<shared_ptr<T>, shared_ptr<T>, bool> |
747 | { |
748 | typedef bool result_type; |
749 | bool operator()(shared_ptr<T> const&, shared_ptr<T> const&) const noexcept; |
750 | bool operator()(shared_ptr<T> const&, weak_ptr<T> const&) const noexcept; |
751 | bool operator()(weak_ptr<T> const&, shared_ptr<T> const&) const noexcept; |
752 | }; |
753 | |
754 | template<class T> |
755 | struct owner_less<weak_ptr<T> > |
756 | : binary_function<weak_ptr<T>, weak_ptr<T>, bool> |
757 | { |
758 | typedef bool result_type; |
759 | bool operator()(weak_ptr<T> const&, weak_ptr<T> const&) const noexcept; |
760 | bool operator()(shared_ptr<T> const&, weak_ptr<T> const&) const noexcept; |
761 | bool operator()(weak_ptr<T> const&, shared_ptr<T> const&) const noexcept; |
762 | }; |
763 | |
764 | template <> // Added in C++14 |
765 | struct owner_less<void> |
766 | { |
767 | template <class _Tp, class _Up> |
768 | bool operator()( shared_ptr<_Tp> const& __x, shared_ptr<_Up> const& __y) const noexcept; |
769 | template <class _Tp, class _Up> |
770 | bool operator()( shared_ptr<_Tp> const& __x, weak_ptr<_Up> const& __y) const noexcept; |
771 | template <class _Tp, class _Up> |
772 | bool operator()( weak_ptr<_Tp> const& __x, shared_ptr<_Up> const& __y) const noexcept; |
773 | template <class _Tp, class _Up> |
774 | bool operator()( weak_ptr<_Tp> const& __x, weak_ptr<_Up> const& __y) const noexcept; |
775 | |
776 | typedef void is_transparent; |
777 | }; |
778 | |
779 | template<class T> |
780 | class enable_shared_from_this |
781 | { |
782 | protected: |
783 | constexpr enable_shared_from_this() noexcept; |
784 | enable_shared_from_this(enable_shared_from_this const&) noexcept; |
785 | enable_shared_from_this& operator=(enable_shared_from_this const&) noexcept; |
786 | ~enable_shared_from_this(); |
787 | public: |
788 | shared_ptr<T> shared_from_this(); |
789 | shared_ptr<T const> shared_from_this() const; |
790 | }; |
791 | |
792 | template<class T> |
793 | bool atomic_is_lock_free(const shared_ptr<T>* p); |
794 | template<class T> |
795 | shared_ptr<T> atomic_load(const shared_ptr<T>* p); |
796 | template<class T> |
797 | shared_ptr<T> atomic_load_explicit(const shared_ptr<T>* p, memory_order mo); |
798 | template<class T> |
799 | void atomic_store(shared_ptr<T>* p, shared_ptr<T> r); |
800 | template<class T> |
801 | void atomic_store_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo); |
802 | template<class T> |
803 | shared_ptr<T> atomic_exchange(shared_ptr<T>* p, shared_ptr<T> r); |
804 | template<class T> |
805 | shared_ptr<T> |
806 | atomic_exchange_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo); |
807 | template<class T> |
808 | bool |
809 | atomic_compare_exchange_weak(shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w); |
810 | template<class T> |
811 | bool |
812 | atomic_compare_exchange_strong( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w); |
813 | template<class T> |
814 | bool |
815 | atomic_compare_exchange_weak_explicit(shared_ptr<T>* p, shared_ptr<T>* v, |
816 | shared_ptr<T> w, memory_order success, |
817 | memory_order failure); |
818 | template<class T> |
819 | bool |
820 | atomic_compare_exchange_strong_explicit(shared_ptr<T>* p, shared_ptr<T>* v, |
821 | shared_ptr<T> w, memory_order success, |
822 | memory_order failure); |
823 | // Hash support |
824 | template <class T> struct hash; |
825 | template <class T, class D> struct hash<unique_ptr<T, D> >; |
826 | template <class T> struct hash<shared_ptr<T> >; |
827 | |
828 | template <class T, class Alloc> |
829 | inline constexpr bool uses_allocator_v = uses_allocator<T, Alloc>::value; |
830 | |
831 | // [ptr.align] |
832 | void* align(size_t alignment, size_t size, void*& ptr, size_t& space); |
833 | |
834 | template<size_t N, class T> |
835 | [[nodiscard]] constexpr T* assume_aligned(T* ptr); // since C++20 |
836 | |
837 | } // std |
838 | |
839 | */ |
840 | |
841 | #include <__assert> // all public C++ headers provide the assertion handler |
842 | #include <__config> |
843 | #include <__memory/addressof.h> |
844 | #include <__memory/allocate_at_least.h> |
845 | #include <__memory/allocation_guard.h> |
846 | #include <__memory/allocator.h> |
847 | #include <__memory/allocator_arg_t.h> |
848 | #include <__memory/allocator_traits.h> |
849 | #include <__memory/assume_aligned.h> |
850 | #include <__memory/auto_ptr.h> |
851 | #include <__memory/compressed_pair.h> |
852 | #include <__memory/concepts.h> |
853 | #include <__memory/construct_at.h> |
854 | #include <__memory/pointer_traits.h> |
855 | #include <__memory/ranges_construct_at.h> |
856 | #include <__memory/ranges_uninitialized_algorithms.h> |
857 | #include <__memory/raw_storage_iterator.h> |
858 | #include <__memory/shared_ptr.h> |
859 | #include <__memory/temporary_buffer.h> |
860 | #include <__memory/uninitialized_algorithms.h> |
861 | #include <__memory/unique_ptr.h> |
862 | #include <__memory/uses_allocator.h> |
863 | #include <cstddef> |
864 | #include <cstdint> |
865 | #include <cstring> |
866 | #include <iosfwd> |
867 | #include <new> |
868 | #include <stdexcept> |
869 | #include <tuple> |
870 | #include <type_traits> |
871 | #include <typeinfo> |
872 | #include <version> |
873 | |
874 | #ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES |
875 | # include <iterator> |
876 | # include <utility> |
877 | #endif |
878 | |
879 | // standard-mandated includes |
880 | #include <compare> |
881 | |
882 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
883 | # pragma GCC system_header |
884 | #endif |
885 | |
886 | _LIBCPP_BEGIN_NAMESPACE_STD |
887 | |
888 | template <class _Alloc, class _Ptr> |
889 | _LIBCPP_INLINE_VISIBILITY |
890 | void __construct_forward_with_exception_guarantees(_Alloc& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __begin2) { |
891 | static_assert(__is_cpp17_move_insertable<_Alloc>::value, |
892 | "The specified type does not meet the requirements of Cpp17MoveInsertable" ); |
893 | typedef allocator_traits<_Alloc> _Traits; |
894 | for (; __begin1 != __end1; ++__begin1, (void)++__begin2) { |
895 | _Traits::construct(__a, _VSTD::__to_address(__begin2), |
896 | #ifdef _LIBCPP_NO_EXCEPTIONS |
897 | _VSTD::move(*__begin1) |
898 | #else |
899 | _VSTD::move_if_noexcept(*__begin1) |
900 | #endif |
901 | ); |
902 | } |
903 | } |
904 | |
905 | template <class _Alloc, class _Tp, typename enable_if< |
906 | (__is_default_allocator<_Alloc>::value || !__has_construct<_Alloc, _Tp*, _Tp>::value) && |
907 | is_trivially_move_constructible<_Tp>::value |
908 | >::type> |
909 | _LIBCPP_INLINE_VISIBILITY |
910 | void __construct_forward_with_exception_guarantees(_Alloc&, _Tp* __begin1, _Tp* __end1, _Tp*& __begin2) { |
911 | ptrdiff_t _Np = __end1 - __begin1; |
912 | if (_Np > 0) { |
913 | _VSTD::memcpy(__begin2, __begin1, _Np * sizeof(_Tp)); |
914 | __begin2 += _Np; |
915 | } |
916 | } |
917 | |
918 | template <class _Alloc, class _Iter, class _Ptr> |
919 | _LIBCPP_INLINE_VISIBILITY |
920 | void __construct_range_forward(_Alloc& __a, _Iter __begin1, _Iter __end1, _Ptr& __begin2) { |
921 | typedef allocator_traits<_Alloc> _Traits; |
922 | for (; __begin1 != __end1; ++__begin1, (void) ++__begin2) { |
923 | _Traits::construct(__a, _VSTD::__to_address(__begin2), *__begin1); |
924 | } |
925 | } |
926 | |
927 | template <class _Alloc, class _Source, class _Dest, |
928 | class _RawSource = typename remove_const<_Source>::type, |
929 | class _RawDest = typename remove_const<_Dest>::type, |
930 | class = |
931 | typename enable_if< |
932 | is_trivially_copy_constructible<_Dest>::value && |
933 | is_same<_RawSource, _RawDest>::value && |
934 | (__is_default_allocator<_Alloc>::value || !__has_construct<_Alloc, _Dest*, _Source&>::value) |
935 | >::type> |
936 | _LIBCPP_INLINE_VISIBILITY |
937 | void __construct_range_forward(_Alloc&, _Source* __begin1, _Source* __end1, _Dest*& __begin2) { |
938 | ptrdiff_t _Np = __end1 - __begin1; |
939 | if (_Np > 0) { |
940 | _VSTD::memcpy(const_cast<_RawDest*>(__begin2), __begin1, _Np * sizeof(_Dest)); |
941 | __begin2 += _Np; |
942 | } |
943 | } |
944 | |
945 | template <class _Alloc, class _Ptr> |
946 | _LIBCPP_INLINE_VISIBILITY |
947 | void __construct_backward_with_exception_guarantees(_Alloc& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __end2) { |
948 | static_assert(__is_cpp17_move_insertable<_Alloc>::value, |
949 | "The specified type does not meet the requirements of Cpp17MoveInsertable" ); |
950 | typedef allocator_traits<_Alloc> _Traits; |
951 | while (__end1 != __begin1) { |
952 | _Traits::construct(__a, _VSTD::__to_address(__end2 - 1), |
953 | #ifdef _LIBCPP_NO_EXCEPTIONS |
954 | _VSTD::move(*--__end1) |
955 | #else |
956 | _VSTD::move_if_noexcept(*--__end1) |
957 | #endif |
958 | ); |
959 | --__end2; |
960 | } |
961 | } |
962 | |
963 | template <class _Alloc, class _Tp, class = typename enable_if< |
964 | (__is_default_allocator<_Alloc>::value || !__has_construct<_Alloc, _Tp*, _Tp>::value) && |
965 | is_trivially_move_constructible<_Tp>::value |
966 | >::type> |
967 | _LIBCPP_INLINE_VISIBILITY |
968 | void __construct_backward_with_exception_guarantees(_Alloc&, _Tp* __begin1, _Tp* __end1, _Tp*& __end2) { |
969 | ptrdiff_t _Np = __end1 - __begin1; |
970 | __end2 -= _Np; |
971 | if (_Np > 0) |
972 | _VSTD::memcpy(static_cast<void*>(__end2), static_cast<void const*>(__begin1), _Np * sizeof(_Tp)); |
973 | } |
974 | |
975 | struct __destruct_n |
976 | { |
977 | private: |
978 | size_t __size_; |
979 | |
980 | template <class _Tp> |
981 | _LIBCPP_INLINE_VISIBILITY void __process(_Tp* __p, false_type) _NOEXCEPT |
982 | {for (size_t __i = 0; __i < __size_; ++__i, ++__p) __p->~_Tp();} |
983 | |
984 | template <class _Tp> |
985 | _LIBCPP_INLINE_VISIBILITY void __process(_Tp*, true_type) _NOEXCEPT |
986 | {} |
987 | |
988 | _LIBCPP_INLINE_VISIBILITY void __incr(false_type) _NOEXCEPT |
989 | {++__size_;} |
990 | _LIBCPP_INLINE_VISIBILITY void __incr(true_type) _NOEXCEPT |
991 | {} |
992 | |
993 | _LIBCPP_INLINE_VISIBILITY void __set(size_t __s, false_type) _NOEXCEPT |
994 | {__size_ = __s;} |
995 | _LIBCPP_INLINE_VISIBILITY void __set(size_t, true_type) _NOEXCEPT |
996 | {} |
997 | public: |
998 | _LIBCPP_INLINE_VISIBILITY explicit __destruct_n(size_t __s) _NOEXCEPT |
999 | : __size_(__s) {} |
1000 | |
1001 | template <class _Tp> |
1002 | _LIBCPP_INLINE_VISIBILITY void __incr() _NOEXCEPT |
1003 | {__incr(integral_constant<bool, is_trivially_destructible<_Tp>::value>());} |
1004 | |
1005 | template <class _Tp> |
1006 | _LIBCPP_INLINE_VISIBILITY void __set(size_t __s, _Tp*) _NOEXCEPT |
1007 | {__set(__s, integral_constant<bool, is_trivially_destructible<_Tp>::value>());} |
1008 | |
1009 | template <class _Tp> |
1010 | _LIBCPP_INLINE_VISIBILITY void operator()(_Tp* __p) _NOEXCEPT |
1011 | {__process(__p, integral_constant<bool, is_trivially_destructible<_Tp>::value>());} |
1012 | }; |
1013 | |
1014 | _LIBCPP_FUNC_VIS void* align(size_t __align, size_t __sz, void*& __ptr, size_t& __space); |
1015 | |
1016 | // --- Helper for container swap -- |
1017 | template <typename _Alloc> |
1018 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 |
1019 | void __swap_allocator(_Alloc & __a1, _Alloc & __a2, true_type) |
1020 | #if _LIBCPP_STD_VER > 11 |
1021 | _NOEXCEPT |
1022 | #else |
1023 | _NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value) |
1024 | #endif |
1025 | { |
1026 | using _VSTD::swap; |
1027 | swap(__a1, __a2); |
1028 | } |
1029 | |
1030 | template <typename _Alloc> |
1031 | inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 |
1032 | void __swap_allocator(_Alloc &, _Alloc &, false_type) _NOEXCEPT {} |
1033 | |
1034 | template <typename _Alloc> |
1035 | inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 |
1036 | void __swap_allocator(_Alloc & __a1, _Alloc & __a2) |
1037 | #if _LIBCPP_STD_VER > 11 |
1038 | _NOEXCEPT |
1039 | #else |
1040 | _NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value) |
1041 | #endif |
1042 | { |
1043 | _VSTD::__swap_allocator(__a1, __a2, |
1044 | integral_constant<bool, allocator_traits<_Alloc>::propagate_on_container_swap::value>()); |
1045 | } |
1046 | |
1047 | template <typename _Alloc, typename _Traits=allocator_traits<_Alloc> > |
1048 | struct __noexcept_move_assign_container : public integral_constant<bool, |
1049 | _Traits::propagate_on_container_move_assignment::value |
1050 | #if _LIBCPP_STD_VER > 14 |
1051 | || _Traits::is_always_equal::value |
1052 | #else |
1053 | && is_nothrow_move_assignable<_Alloc>::value |
1054 | #endif |
1055 | > {}; |
1056 | |
1057 | |
1058 | template <class _Tp, class _Alloc> |
1059 | struct __temp_value { |
1060 | typedef allocator_traits<_Alloc> _Traits; |
1061 | |
1062 | typename aligned_storage<sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)>::type __v; |
1063 | _Alloc &__a; |
1064 | |
1065 | _Tp *__addr() { return reinterpret_cast<_Tp *>(addressof(__v)); } |
1066 | _Tp & get() { return *__addr(); } |
1067 | |
1068 | template<class... _Args> |
1069 | _LIBCPP_NO_CFI |
1070 | __temp_value(_Alloc &__alloc, _Args&& ... __args) : __a(__alloc) { |
1071 | _Traits::construct(__a, reinterpret_cast<_Tp*>(addressof(__v)), |
1072 | _VSTD::forward<_Args>(__args)...); |
1073 | } |
1074 | |
1075 | ~__temp_value() { _Traits::destroy(__a, __addr()); } |
1076 | }; |
1077 | |
1078 | template<typename _Alloc, typename = void, typename = void> |
1079 | struct __is_allocator : false_type {}; |
1080 | |
1081 | template<typename _Alloc> |
1082 | struct __is_allocator<_Alloc, |
1083 | typename __void_t<typename _Alloc::value_type>::type, |
1084 | typename __void_t<decltype(declval<_Alloc&>().allocate(size_t(0)))>::type |
1085 | > |
1086 | : true_type {}; |
1087 | |
1088 | // __builtin_new_allocator -- A non-templated helper for allocating and |
1089 | // deallocating memory using __builtin_operator_new and |
1090 | // __builtin_operator_delete. It should be used in preference to |
1091 | // `std::allocator<T>` to avoid additional instantiations. |
1092 | struct __builtin_new_allocator { |
1093 | struct __builtin_new_deleter { |
1094 | typedef void* pointer_type; |
1095 | |
1096 | _LIBCPP_CONSTEXPR explicit __builtin_new_deleter(size_t __size, size_t __align) |
1097 | : __size_(__size), __align_(__align) {} |
1098 | |
1099 | void operator()(void* __p) const _NOEXCEPT { |
1100 | _VSTD::__libcpp_deallocate(ptr: __p, size: __size_, align: __align_); |
1101 | } |
1102 | |
1103 | private: |
1104 | size_t __size_; |
1105 | size_t __align_; |
1106 | }; |
1107 | |
1108 | typedef unique_ptr<void, __builtin_new_deleter> __holder_t; |
1109 | |
1110 | static __holder_t __allocate_bytes(size_t __s, size_t __align) { |
1111 | return __holder_t(_VSTD::__libcpp_allocate(size: __s, __align), |
1112 | __builtin_new_deleter(__s, __align)); |
1113 | } |
1114 | |
1115 | static void __deallocate_bytes(void* __p, size_t __s, |
1116 | size_t __align) _NOEXCEPT { |
1117 | _VSTD::__libcpp_deallocate(ptr: __p, size: __s, __align); |
1118 | } |
1119 | |
1120 | template <class _Tp> |
1121 | _LIBCPP_NODEBUG _LIBCPP_ALWAYS_INLINE |
1122 | static __holder_t __allocate_type(size_t __n) { |
1123 | return __allocate_bytes(s: __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)); |
1124 | } |
1125 | |
1126 | template <class _Tp> |
1127 | _LIBCPP_NODEBUG _LIBCPP_ALWAYS_INLINE |
1128 | static void __deallocate_type(void* __p, size_t __n) _NOEXCEPT { |
1129 | __deallocate_bytes(__p, s: __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)); |
1130 | } |
1131 | }; |
1132 | |
1133 | _LIBCPP_END_NAMESPACE_STD |
1134 | |
1135 | #if defined(_LIBCPP_HAS_PARALLEL_ALGORITHMS) && _LIBCPP_STD_VER >= 17 |
1136 | # include <__pstl_memory> |
1137 | #endif |
1138 | |
1139 | #endif // _LIBCPP_MEMORY |
1140 | |