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_FORWARD_LIST |
11 | #define _LIBCPP_FORWARD_LIST |
12 | |
13 | /* |
14 | forward_list synopsis |
15 | |
16 | namespace std |
17 | { |
18 | |
19 | template <class T, class Allocator = allocator<T>> |
20 | class forward_list |
21 | { |
22 | public: |
23 | typedef T value_type; |
24 | typedef Allocator allocator_type; |
25 | |
26 | typedef value_type& reference; |
27 | typedef const value_type& const_reference; |
28 | typedef typename allocator_traits<allocator_type>::pointer pointer; |
29 | typedef typename allocator_traits<allocator_type>::const_pointer const_pointer; |
30 | typedef typename allocator_traits<allocator_type>::size_type size_type; |
31 | typedef typename allocator_traits<allocator_type>::difference_type difference_type; |
32 | |
33 | typedef <details> iterator; |
34 | typedef <details> const_iterator; |
35 | |
36 | forward_list() |
37 | noexcept(is_nothrow_default_constructible<allocator_type>::value); |
38 | explicit forward_list(const allocator_type& a); |
39 | explicit forward_list(size_type n); |
40 | explicit forward_list(size_type n, const allocator_type& a); // C++14 |
41 | forward_list(size_type n, const value_type& v); |
42 | forward_list(size_type n, const value_type& v, const allocator_type& a); |
43 | template <class InputIterator> |
44 | forward_list(InputIterator first, InputIterator last); |
45 | template <class InputIterator> |
46 | forward_list(InputIterator first, InputIterator last, const allocator_type& a); |
47 | template<container-compatible-range<T> R> |
48 | forward_list(from_range_t, R&& rg, const Allocator& = Allocator()); // C++23 |
49 | forward_list(const forward_list& x); |
50 | forward_list(const forward_list& x, const allocator_type& a); |
51 | forward_list(forward_list&& x) |
52 | noexcept(is_nothrow_move_constructible<allocator_type>::value); |
53 | forward_list(forward_list&& x, const allocator_type& a); |
54 | forward_list(initializer_list<value_type> il); |
55 | forward_list(initializer_list<value_type> il, const allocator_type& a); |
56 | |
57 | ~forward_list(); |
58 | |
59 | forward_list& operator=(const forward_list& x); |
60 | forward_list& operator=(forward_list&& x) |
61 | noexcept((__node_traits::propagate_on_container_move_assignment::value && |
62 | is_nothrow_move_assignable<allocator_type>::value) || |
63 | allocator_traits<allocator_type>::is_always_equal::value); |
64 | forward_list& operator=(initializer_list<value_type> il); |
65 | |
66 | template <class InputIterator> |
67 | void assign(InputIterator first, InputIterator last); |
68 | template<container-compatible-range<T> R> |
69 | void assign_range(R&& rg); // C++23 |
70 | void assign(size_type n, const value_type& v); |
71 | void assign(initializer_list<value_type> il); |
72 | |
73 | allocator_type get_allocator() const noexcept; |
74 | |
75 | iterator begin() noexcept; |
76 | const_iterator begin() const noexcept; |
77 | iterator end() noexcept; |
78 | const_iterator end() const noexcept; |
79 | |
80 | const_iterator cbegin() const noexcept; |
81 | const_iterator cend() const noexcept; |
82 | |
83 | iterator before_begin() noexcept; |
84 | const_iterator before_begin() const noexcept; |
85 | const_iterator cbefore_begin() const noexcept; |
86 | |
87 | bool empty() const noexcept; |
88 | size_type max_size() const noexcept; |
89 | |
90 | reference front(); |
91 | const_reference front() const; |
92 | |
93 | template <class... Args> reference emplace_front(Args&&... args); // reference in C++17 |
94 | void push_front(const value_type& v); |
95 | void push_front(value_type&& v); |
96 | template<container-compatible-range<T> R> |
97 | void prepend_range(R&& rg); // C++23 |
98 | |
99 | void pop_front(); |
100 | |
101 | template <class... Args> |
102 | iterator emplace_after(const_iterator p, Args&&... args); |
103 | iterator insert_after(const_iterator p, const value_type& v); |
104 | iterator insert_after(const_iterator p, value_type&& v); |
105 | iterator insert_after(const_iterator p, size_type n, const value_type& v); |
106 | template <class InputIterator> |
107 | iterator insert_after(const_iterator p, |
108 | InputIterator first, InputIterator last); |
109 | template<container-compatible-range<T> R> |
110 | iterator insert_range_after(const_iterator position, R&& rg); // C++23 |
111 | iterator insert_after(const_iterator p, initializer_list<value_type> il); |
112 | |
113 | iterator erase_after(const_iterator p); |
114 | iterator erase_after(const_iterator first, const_iterator last); |
115 | |
116 | void swap(forward_list& x) |
117 | noexcept(allocator_traits<allocator_type>::is_always_equal::value); // C++17 |
118 | |
119 | void resize(size_type n); |
120 | void resize(size_type n, const value_type& v); |
121 | void clear() noexcept; |
122 | |
123 | void splice_after(const_iterator p, forward_list& x); |
124 | void splice_after(const_iterator p, forward_list&& x); |
125 | void splice_after(const_iterator p, forward_list& x, const_iterator i); |
126 | void splice_after(const_iterator p, forward_list&& x, const_iterator i); |
127 | void splice_after(const_iterator p, forward_list& x, |
128 | const_iterator first, const_iterator last); |
129 | void splice_after(const_iterator p, forward_list&& x, |
130 | const_iterator first, const_iterator last); |
131 | size_type remove(const value_type& v); // void before C++20 |
132 | template <class Predicate> |
133 | size_type remove_if(Predicate pred); // void before C++20 |
134 | size_type unique(); // void before C++20 |
135 | template <class BinaryPredicate> |
136 | size_type unique(BinaryPredicate binary_pred); // void before C++20 |
137 | void merge(forward_list& x); |
138 | void merge(forward_list&& x); |
139 | template <class Compare> void merge(forward_list& x, Compare comp); |
140 | template <class Compare> void merge(forward_list&& x, Compare comp); |
141 | void sort(); |
142 | template <class Compare> void sort(Compare comp); |
143 | void reverse() noexcept; |
144 | }; |
145 | |
146 | |
147 | template <class InputIterator, class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>> |
148 | forward_list(InputIterator, InputIterator, Allocator = Allocator()) |
149 | -> forward_list<typename iterator_traits<InputIterator>::value_type, Allocator>; // C++17 |
150 | |
151 | template<ranges::input_range R, class Allocator = allocator<ranges::range_value_t<R>>> |
152 | forward_list(from_range_t, R&&, Allocator = Allocator()) |
153 | -> forward_list<ranges::range_value_t<R>, Allocator>; // C++23 |
154 | |
155 | template <class T, class Allocator> |
156 | bool operator==(const forward_list<T, Allocator>& x, |
157 | const forward_list<T, Allocator>& y); |
158 | |
159 | template <class T, class Allocator> |
160 | bool operator< (const forward_list<T, Allocator>& x, |
161 | const forward_list<T, Allocator>& y); // removed in C++20 |
162 | |
163 | template <class T, class Allocator> |
164 | bool operator!=(const forward_list<T, Allocator>& x, |
165 | const forward_list<T, Allocator>& y); // removed in C++20 |
166 | |
167 | template <class T, class Allocator> |
168 | bool operator> (const forward_list<T, Allocator>& x, |
169 | const forward_list<T, Allocator>& y); // removed in C++20 |
170 | |
171 | template <class T, class Allocator> |
172 | bool operator>=(const forward_list<T, Allocator>& x, |
173 | const forward_list<T, Allocator>& y); // removed in C++20 |
174 | |
175 | template <class T, class Allocator> |
176 | bool operator<=(const forward_list<T, Allocator>& x, |
177 | const forward_list<T, Allocator>& y); // removed in C++20 |
178 | |
179 | template<class T, class Allocator> |
180 | synth-three-way-result<T> operator<=>(const forward_list<T, Allocator>& x, |
181 | const forward_list<T, Allocator>& y); // since C++20 |
182 | |
183 | template <class T, class Allocator> |
184 | void swap(forward_list<T, Allocator>& x, forward_list<T, Allocator>& y) |
185 | noexcept(noexcept(x.swap(y))); |
186 | |
187 | template <class T, class Allocator, class U> |
188 | typename forward_list<T, Allocator>::size_type |
189 | erase(forward_list<T, Allocator>& c, const U& value); // C++20 |
190 | template <class T, class Allocator, class Predicate> |
191 | typename forward_list<T, Allocator>::size_type |
192 | erase_if(forward_list<T, Allocator>& c, Predicate pred); // C++20 |
193 | |
194 | } // std |
195 | |
196 | */ |
197 | |
198 | #if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) |
199 | # include <__cxx03/forward_list> |
200 | #else |
201 | # include <__algorithm/comp.h> |
202 | # include <__algorithm/lexicographical_compare.h> |
203 | # include <__algorithm/lexicographical_compare_three_way.h> |
204 | # include <__algorithm/min.h> |
205 | # include <__assert> |
206 | # include <__config> |
207 | # include <__cstddef/nullptr_t.h> |
208 | # include <__iterator/distance.h> |
209 | # include <__iterator/iterator_traits.h> |
210 | # include <__iterator/move_iterator.h> |
211 | # include <__iterator/next.h> |
212 | # include <__memory/addressof.h> |
213 | # include <__memory/allocation_guard.h> |
214 | # include <__memory/allocator.h> |
215 | # include <__memory/allocator_traits.h> |
216 | # include <__memory/compressed_pair.h> |
217 | # include <__memory/construct_at.h> |
218 | # include <__memory/pointer_traits.h> |
219 | # include <__memory/swap_allocator.h> |
220 | # include <__memory_resource/polymorphic_allocator.h> |
221 | # include <__new/launder.h> |
222 | # include <__ranges/access.h> |
223 | # include <__ranges/concepts.h> |
224 | # include <__ranges/container_compatible_range.h> |
225 | # include <__ranges/from_range.h> |
226 | # include <__type_traits/conditional.h> |
227 | # include <__type_traits/container_traits.h> |
228 | # include <__type_traits/enable_if.h> |
229 | # include <__type_traits/is_allocator.h> |
230 | # include <__type_traits/is_const.h> |
231 | # include <__type_traits/is_nothrow_assignable.h> |
232 | # include <__type_traits/is_nothrow_constructible.h> |
233 | # include <__type_traits/is_pointer.h> |
234 | # include <__type_traits/is_same.h> |
235 | # include <__type_traits/is_swappable.h> |
236 | # include <__type_traits/remove_cv.h> |
237 | # include <__type_traits/type_identity.h> |
238 | # include <__utility/forward.h> |
239 | # include <__utility/move.h> |
240 | # include <__utility/swap.h> |
241 | # include <limits> |
242 | # include <version> |
243 | |
244 | // standard-mandated includes |
245 | |
246 | // [iterator.range] |
247 | # include <__iterator/access.h> |
248 | # include <__iterator/data.h> |
249 | # include <__iterator/empty.h> |
250 | # include <__iterator/reverse_access.h> |
251 | # include <__iterator/size.h> |
252 | |
253 | // [forward.list.syn] |
254 | # include <compare> |
255 | # include <initializer_list> |
256 | |
257 | # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
258 | # pragma GCC system_header |
259 | # endif |
260 | |
261 | _LIBCPP_PUSH_MACROS |
262 | # include <__undef_macros> |
263 | |
264 | _LIBCPP_BEGIN_NAMESPACE_STD |
265 | |
266 | template <class _Tp, class _VoidPtr> |
267 | struct __forward_list_node; |
268 | template <class _NodePtr> |
269 | struct __forward_begin_node; |
270 | |
271 | template <class> |
272 | struct __forward_list_node_value_type; |
273 | |
274 | template <class _Tp, class _VoidPtr> |
275 | struct __forward_list_node_value_type<__forward_list_node<_Tp, _VoidPtr> > { |
276 | typedef _Tp type; |
277 | }; |
278 | |
279 | template <class _NodePtr> |
280 | struct __forward_node_traits { |
281 | typedef __remove_cv_t<typename pointer_traits<_NodePtr>::element_type> __node_type; |
282 | typedef typename __forward_list_node_value_type<__node_type>::type __node_value_type; |
283 | typedef _NodePtr __node_pointer; |
284 | typedef __forward_begin_node<_NodePtr> __begin_node; |
285 | typedef __rebind_pointer_t<_NodePtr, __begin_node> __begin_node_pointer; |
286 | |
287 | // TODO(LLVM 22): Remove this check |
288 | # ifndef _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB |
289 | static_assert(sizeof(__begin_node_pointer) == sizeof(__node_pointer) && _LIBCPP_ALIGNOF(__begin_node_pointer) == |
290 | _LIBCPP_ALIGNOF(__node_pointer), |
291 | "It looks like you are using std::forward_list with a fancy pointer type that thas a different " |
292 | "representation depending on whether it points to a forward_list base pointer or a forward_list node " |
293 | "pointer (both of which are implementation details of the standard library). This means that your ABI " |
294 | "is being broken between LLVM 19 and LLVM 20. If you don't care about your ABI being broken, define " |
295 | "the _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB macro to silence this diagnostic." ); |
296 | # endif |
297 | }; |
298 | |
299 | template <class _NodePtr> |
300 | struct __forward_begin_node { |
301 | typedef _NodePtr pointer; |
302 | typedef __rebind_pointer_t<_NodePtr, __forward_begin_node> __begin_node_pointer; |
303 | |
304 | pointer __next_; |
305 | |
306 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_begin_node() : __next_(nullptr) {} |
307 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __forward_begin_node(pointer __n) : __next_(__n) {} |
308 | }; |
309 | |
310 | template <class _Tp, class _VoidPtr> |
311 | using __begin_node_of _LIBCPP_NODEBUG = |
312 | __forward_begin_node<__rebind_pointer_t<_VoidPtr, __forward_list_node<_Tp, _VoidPtr> > >; |
313 | |
314 | template <class _Tp, class _VoidPtr> |
315 | struct __forward_list_node : public __begin_node_of<_Tp, _VoidPtr> { |
316 | typedef _Tp value_type; |
317 | typedef __begin_node_of<_Tp, _VoidPtr> _Base; |
318 | typedef typename _Base::pointer _NodePtr; |
319 | |
320 | // We allow starting the lifetime of nodes without initializing the value held by the node, |
321 | // since that is handled by the list itself in order to be allocator-aware. |
322 | # ifndef _LIBCPP_CXX03_LANG |
323 | |
324 | private: |
325 | union { |
326 | _Tp __value_; |
327 | }; |
328 | |
329 | public: |
330 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return __value_; } |
331 | # else |
332 | |
333 | private: |
334 | _ALIGNAS_TYPE(_Tp) char __buffer_[sizeof(_Tp)]; |
335 | |
336 | public: |
337 | _LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return *std::__launder(reinterpret_cast<_Tp*>(&__buffer_)); } |
338 | # endif |
339 | |
340 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __forward_list_node(_NodePtr __next) : _Base(__next) {} |
341 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI ~__forward_list_node() {} |
342 | }; |
343 | |
344 | template <class _Tp, class _Alloc = allocator<_Tp> > |
345 | class forward_list; |
346 | template <class _NodeConstPtr> |
347 | class __forward_list_const_iterator; |
348 | |
349 | template <class _NodePtr> |
350 | class __forward_list_iterator { |
351 | typedef __forward_node_traits<_NodePtr> __traits; |
352 | typedef typename __traits::__node_type __node_type; |
353 | typedef typename __traits::__begin_node __begin_node_type; |
354 | typedef typename __traits::__node_pointer __node_pointer; |
355 | typedef typename __traits::__begin_node_pointer __begin_node_pointer; |
356 | |
357 | __begin_node_pointer __ptr_; |
358 | |
359 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __forward_list_iterator(nullptr_t) _NOEXCEPT |
360 | : __ptr_(nullptr) {} |
361 | |
362 | _LIBCPP_CONSTEXPR_SINCE_CXX26 |
363 | _LIBCPP_HIDE_FROM_ABI explicit __forward_list_iterator(__begin_node_pointer __p) _NOEXCEPT : __ptr_(__p) {} |
364 | |
365 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __forward_list_iterator(__node_pointer __p) _NOEXCEPT |
366 | : __ptr_(std::__static_fancy_pointer_cast<__begin_node_pointer>(__p)) {} |
367 | |
368 | template <class, class> |
369 | friend class forward_list; |
370 | template <class> |
371 | friend class __forward_list_const_iterator; |
372 | |
373 | public: |
374 | typedef forward_iterator_tag iterator_category; |
375 | typedef typename __traits::__node_value_type value_type; |
376 | typedef value_type& reference; |
377 | typedef typename pointer_traits<__node_pointer>::difference_type difference_type; |
378 | typedef __rebind_pointer_t<__node_pointer, value_type> pointer; |
379 | |
380 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_list_iterator() _NOEXCEPT : __ptr_(nullptr) {} |
381 | |
382 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI reference operator*() const { |
383 | return std::__static_fancy_pointer_cast<__node_pointer>(__ptr_)->__get_value(); |
384 | } |
385 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI pointer operator->() const { |
386 | return pointer_traits<pointer>::pointer_to(std::__static_fancy_pointer_cast<__node_pointer>(__ptr_)->__get_value()); |
387 | } |
388 | |
389 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_list_iterator& operator++() { |
390 | __ptr_ = std::__static_fancy_pointer_cast<__begin_node_pointer>(__ptr_->__next_); |
391 | return *this; |
392 | } |
393 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_list_iterator operator++(int) { |
394 | __forward_list_iterator __t(*this); |
395 | ++(*this); |
396 | return __t; |
397 | } |
398 | |
399 | friend _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI bool |
400 | operator==(const __forward_list_iterator& __x, const __forward_list_iterator& __y) { |
401 | return __x.__ptr_ == __y.__ptr_; |
402 | } |
403 | friend _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI bool |
404 | operator!=(const __forward_list_iterator& __x, const __forward_list_iterator& __y) { |
405 | return !(__x == __y); |
406 | } |
407 | }; |
408 | |
409 | template <class _NodeConstPtr> |
410 | class __forward_list_const_iterator { |
411 | static_assert(!is_const<typename pointer_traits<_NodeConstPtr>::element_type>::value, "" ); |
412 | typedef _NodeConstPtr _NodePtr; |
413 | |
414 | typedef __forward_node_traits<_NodePtr> __traits; |
415 | typedef typename __traits::__node_type __node_type; |
416 | typedef typename __traits::__begin_node __begin_node_type; |
417 | typedef typename __traits::__node_pointer __node_pointer; |
418 | typedef typename __traits::__begin_node_pointer __begin_node_pointer; |
419 | |
420 | __begin_node_pointer __ptr_; |
421 | |
422 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __forward_list_const_iterator(nullptr_t) _NOEXCEPT |
423 | : __ptr_(nullptr) {} |
424 | |
425 | _LIBCPP_CONSTEXPR_SINCE_CXX26 |
426 | _LIBCPP_HIDE_FROM_ABI explicit __forward_list_const_iterator(__begin_node_pointer __p) _NOEXCEPT : __ptr_(__p) {} |
427 | |
428 | _LIBCPP_CONSTEXPR_SINCE_CXX26 |
429 | _LIBCPP_HIDE_FROM_ABI explicit __forward_list_const_iterator(__node_pointer __p) _NOEXCEPT |
430 | : __ptr_(std::__static_fancy_pointer_cast<__begin_node_pointer>(__p)) {} |
431 | |
432 | template <class, class> |
433 | friend class forward_list; |
434 | |
435 | public: |
436 | typedef forward_iterator_tag iterator_category; |
437 | typedef typename __traits::__node_value_type value_type; |
438 | typedef const value_type& reference; |
439 | typedef typename pointer_traits<__node_pointer>::difference_type difference_type; |
440 | typedef __rebind_pointer_t<__node_pointer, const value_type> pointer; |
441 | |
442 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_list_const_iterator() _NOEXCEPT : __ptr_(nullptr) {} |
443 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI |
444 | __forward_list_const_iterator(__forward_list_iterator<__node_pointer> __p) _NOEXCEPT : __ptr_(__p.__ptr_) {} |
445 | |
446 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI reference operator*() const { |
447 | return std::__static_fancy_pointer_cast<__node_pointer>(__ptr_)->__get_value(); |
448 | } |
449 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI pointer operator->() const { |
450 | return pointer_traits<pointer>::pointer_to(std::__static_fancy_pointer_cast<__node_pointer>(__ptr_)->__get_value()); |
451 | } |
452 | |
453 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_list_const_iterator& operator++() { |
454 | __ptr_ = std::__static_fancy_pointer_cast<__begin_node_pointer>(__ptr_->__next_); |
455 | return *this; |
456 | } |
457 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_list_const_iterator operator++(int) { |
458 | __forward_list_const_iterator __t(*this); |
459 | ++(*this); |
460 | return __t; |
461 | } |
462 | |
463 | friend _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI bool |
464 | operator==(const __forward_list_const_iterator& __x, const __forward_list_const_iterator& __y) { |
465 | return __x.__ptr_ == __y.__ptr_; |
466 | } |
467 | friend _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI bool |
468 | operator!=(const __forward_list_const_iterator& __x, const __forward_list_const_iterator& __y) { |
469 | return !(__x == __y); |
470 | } |
471 | }; |
472 | |
473 | template <class _Tp, class _Alloc> |
474 | class __forward_list_base { |
475 | protected: |
476 | typedef _Tp value_type; |
477 | typedef _Alloc allocator_type; |
478 | |
479 | typedef typename allocator_traits<allocator_type>::void_pointer void_pointer; |
480 | typedef __forward_list_node<value_type, void_pointer> __node_type; |
481 | typedef __begin_node_of<value_type, void_pointer> __begin_node; |
482 | typedef __rebind_alloc<allocator_traits<allocator_type>, __node_type> __node_allocator; |
483 | typedef allocator_traits<__node_allocator> __node_traits; |
484 | typedef typename __node_traits::pointer __node_pointer; |
485 | |
486 | typedef __rebind_alloc<allocator_traits<allocator_type>, __begin_node> __begin_node_allocator; |
487 | typedef typename allocator_traits<__begin_node_allocator>::pointer __begin_node_pointer; |
488 | |
489 | _LIBCPP_COMPRESSED_PAIR(__begin_node, __before_begin_, __node_allocator, __alloc_); |
490 | |
491 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __begin_node_pointer __before_begin() _NOEXCEPT { |
492 | return pointer_traits<__begin_node_pointer>::pointer_to(__before_begin_); |
493 | } |
494 | |
495 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __begin_node_pointer __before_begin() const _NOEXCEPT { |
496 | return pointer_traits<__begin_node_pointer>::pointer_to( |
497 | *const_cast<__begin_node*>(std::addressof(__before_begin_))); |
498 | } |
499 | |
500 | typedef __forward_list_iterator<__node_pointer> iterator; |
501 | typedef __forward_list_const_iterator<__node_pointer> const_iterator; |
502 | |
503 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_list_base() |
504 | _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value) |
505 | : __before_begin_(__begin_node()) {} |
506 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __forward_list_base(const allocator_type& __a) |
507 | : __before_begin_(__begin_node()), __alloc_(__node_allocator(__a)) {} |
508 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __forward_list_base(const __node_allocator& __a) |
509 | : __before_begin_(__begin_node()), __alloc_(__a) {} |
510 | |
511 | public: |
512 | # ifndef _LIBCPP_CXX03_LANG |
513 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI |
514 | __forward_list_base(__forward_list_base&& __x) noexcept(is_nothrow_move_constructible<__node_allocator>::value); |
515 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI |
516 | __forward_list_base(__forward_list_base&& __x, const allocator_type& __a); |
517 | # endif // _LIBCPP_CXX03_LANG |
518 | |
519 | __forward_list_base(const __forward_list_base&) = delete; |
520 | __forward_list_base& operator=(const __forward_list_base&) = delete; |
521 | |
522 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI ~__forward_list_base(); |
523 | |
524 | protected: |
525 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __forward_list_base& __x) { |
526 | __copy_assign_alloc(__x, integral_constant<bool, __node_traits::propagate_on_container_copy_assignment::value>()); |
527 | } |
528 | |
529 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__forward_list_base& __x) |
530 | _NOEXCEPT_(!__node_traits::propagate_on_container_move_assignment::value || |
531 | is_nothrow_move_assignable<__node_allocator>::value) { |
532 | __move_assign_alloc(__x, integral_constant<bool, __node_traits::propagate_on_container_move_assignment::value>()); |
533 | } |
534 | |
535 | template <class... _Args> |
536 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __node_pointer |
537 | __create_node(__node_pointer __next, _Args&&... __args) { |
538 | __allocation_guard<__node_allocator> __guard(__alloc_, 1); |
539 | // Begin the lifetime of the node itself. Note that this doesn't begin the lifetime of the value |
540 | // held inside the node, since we need to use the allocator's construct() method for that. |
541 | // |
542 | // We don't use the allocator's construct() method to construct the node itself since the |
543 | // Cpp17FooInsertable named requirements don't require the allocator's construct() method |
544 | // to work on anything other than the value_type. |
545 | std::__construct_at(std::addressof(*__guard.__get()), __next); |
546 | |
547 | // Now construct the value_type using the allocator's construct() method. |
548 | __node_traits::construct(__alloc_, std::addressof(__guard.__get()->__get_value()), std::forward<_Args>(__args)...); |
549 | return __guard.__release_ptr(); |
550 | } |
551 | |
552 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __delete_node(__node_pointer __node) { |
553 | // For the same reason as above, we use the allocator's destroy() method for the value_type, |
554 | // but not for the node itself. |
555 | __node_traits::destroy(__alloc_, std::addressof(__node->__get_value())); |
556 | std::__destroy_at(std::addressof(*__node)); |
557 | __node_traits::deallocate(__alloc_, __node, 1); |
558 | } |
559 | |
560 | public: |
561 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void swap(__forward_list_base& __x) |
562 | # if _LIBCPP_STD_VER >= 14 |
563 | _NOEXCEPT; |
564 | # else |
565 | _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>); |
566 | # endif |
567 | |
568 | protected: |
569 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT; |
570 | |
571 | private: |
572 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __forward_list_base&, false_type) { |
573 | } |
574 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void |
575 | __copy_assign_alloc(const __forward_list_base& __x, true_type) { |
576 | if (__alloc_ != __x.__alloc_) |
577 | clear(); |
578 | __alloc_ = __x.__alloc_; |
579 | } |
580 | |
581 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void |
582 | __move_assign_alloc(__forward_list_base&, false_type) _NOEXCEPT {} |
583 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__forward_list_base& __x, true_type) |
584 | _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value) { |
585 | __alloc_ = std::move(__x.__alloc_); |
586 | } |
587 | }; |
588 | |
589 | # ifndef _LIBCPP_CXX03_LANG |
590 | |
591 | template <class _Tp, class _Alloc> |
592 | _LIBCPP_CONSTEXPR_SINCE_CXX26 inline __forward_list_base<_Tp, _Alloc>::__forward_list_base( |
593 | __forward_list_base&& __x) noexcept(is_nothrow_move_constructible<__node_allocator>::value) |
594 | : __before_begin_(std::move(__x.__before_begin_)), __alloc_(std::move(__x.__alloc_)) { |
595 | __x.__before_begin()->__next_ = nullptr; |
596 | } |
597 | |
598 | template <class _Tp, class _Alloc> |
599 | _LIBCPP_CONSTEXPR_SINCE_CXX26 inline __forward_list_base<_Tp, _Alloc>::__forward_list_base( |
600 | __forward_list_base&& __x, const allocator_type& __a) |
601 | : __before_begin_(__begin_node()), __alloc_(__node_allocator(__a)) { |
602 | if (__alloc_ == __x.__alloc_) { |
603 | __before_begin()->__next_ = __x.__before_begin()->__next_; |
604 | __x.__before_begin()->__next_ = nullptr; |
605 | } |
606 | } |
607 | |
608 | # endif // _LIBCPP_CXX03_LANG |
609 | |
610 | template <class _Tp, class _Alloc> |
611 | _LIBCPP_CONSTEXPR_SINCE_CXX26 __forward_list_base<_Tp, _Alloc>::~__forward_list_base() { |
612 | clear(); |
613 | } |
614 | |
615 | template <class _Tp, class _Alloc> |
616 | _LIBCPP_CONSTEXPR_SINCE_CXX26 inline void __forward_list_base<_Tp, _Alloc>::swap(__forward_list_base& __x) |
617 | # if _LIBCPP_STD_VER >= 14 |
618 | _NOEXCEPT |
619 | # else |
620 | _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>) |
621 | # endif |
622 | { |
623 | std::__swap_allocator(__alloc_, __x.__alloc_); |
624 | using std::swap; |
625 | swap(__before_begin()->__next_, __x.__before_begin()->__next_); |
626 | } |
627 | |
628 | template <class _Tp, class _Alloc> |
629 | _LIBCPP_CONSTEXPR_SINCE_CXX26 void __forward_list_base<_Tp, _Alloc>::clear() _NOEXCEPT { |
630 | for (__node_pointer __p = __before_begin()->__next_; __p != nullptr;) { |
631 | __node_pointer __next = __p->__next_; |
632 | __delete_node(node: __p); |
633 | __p = __next; |
634 | } |
635 | __before_begin()->__next_ = nullptr; |
636 | } |
637 | |
638 | template <class _Tp, class _Alloc /*= allocator<_Tp>*/> |
639 | class forward_list : private __forward_list_base<_Tp, _Alloc> { |
640 | typedef __forward_list_base<_Tp, _Alloc> __base; |
641 | typedef typename __base::__node_allocator __node_allocator; |
642 | typedef typename __base::__node_type __node_type; |
643 | typedef typename __base::__node_traits __node_traits; |
644 | typedef typename __base::__node_pointer __node_pointer; |
645 | typedef typename __base::__begin_node_pointer __begin_node_pointer; |
646 | |
647 | public: |
648 | typedef _Tp value_type; |
649 | typedef _Alloc allocator_type; |
650 | |
651 | static_assert(__check_valid_allocator<allocator_type>::value, "" ); |
652 | |
653 | static_assert(is_same<value_type, typename allocator_type::value_type>::value, |
654 | "Allocator::value_type must be same type as value_type" ); |
655 | |
656 | static_assert(!is_same<allocator_type, __node_allocator>::value, |
657 | "internal allocator type must differ from user-specified type; otherwise overload resolution breaks" ); |
658 | |
659 | typedef value_type& reference; |
660 | typedef const value_type& const_reference; |
661 | typedef typename allocator_traits<allocator_type>::pointer pointer; |
662 | typedef typename allocator_traits<allocator_type>::const_pointer const_pointer; |
663 | typedef typename allocator_traits<allocator_type>::size_type size_type; |
664 | typedef typename allocator_traits<allocator_type>::difference_type difference_type; |
665 | |
666 | typedef typename __base::iterator iterator; |
667 | typedef typename __base::const_iterator const_iterator; |
668 | # if _LIBCPP_STD_VER >= 20 |
669 | typedef size_type __remove_return_type; |
670 | # else |
671 | typedef void __remove_return_type; |
672 | # endif |
673 | |
674 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI forward_list() |
675 | _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value) {} // = default; |
676 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit forward_list(const allocator_type& __a); |
677 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit forward_list(size_type __n); |
678 | # if _LIBCPP_STD_VER >= 14 |
679 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit forward_list(size_type __n, const allocator_type& __a); |
680 | # endif |
681 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI forward_list(size_type __n, const value_type& __v); |
682 | |
683 | template <__enable_if_t<__is_allocator<_Alloc>::value, int> = 0> |
684 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI |
685 | forward_list(size_type __n, const value_type& __v, const allocator_type& __a) |
686 | : __base(__a) { |
687 | insert_after(cbefore_begin(), __n, __v); |
688 | } |
689 | |
690 | template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0> |
691 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI forward_list(_InputIterator __f, _InputIterator __l); |
692 | |
693 | template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0> |
694 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI |
695 | forward_list(_InputIterator __f, _InputIterator __l, const allocator_type& __a); |
696 | |
697 | # if _LIBCPP_STD_VER >= 23 |
698 | template <_ContainerCompatibleRange<_Tp> _Range> |
699 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI |
700 | forward_list(from_range_t, _Range&& __range, const allocator_type& __a = allocator_type()) |
701 | : __base(__a) { |
702 | prepend_range(std::forward<_Range>(__range)); |
703 | } |
704 | # endif |
705 | |
706 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI forward_list(const forward_list& __x); |
707 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI |
708 | forward_list(const forward_list& __x, const __type_identity_t<allocator_type>& __a); |
709 | |
710 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI forward_list& operator=(const forward_list& __x); |
711 | |
712 | # ifndef _LIBCPP_CXX03_LANG |
713 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI |
714 | forward_list(forward_list&& __x) noexcept(is_nothrow_move_constructible<__base>::value) |
715 | : __base(std::move(__x)) {} |
716 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI |
717 | forward_list(forward_list&& __x, const __type_identity_t<allocator_type>& __a); |
718 | |
719 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI forward_list(initializer_list<value_type> __il); |
720 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI |
721 | forward_list(initializer_list<value_type> __il, const allocator_type& __a); |
722 | |
723 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI forward_list& operator=(forward_list&& __x) noexcept( |
724 | (__node_traits::propagate_on_container_move_assignment::value && |
725 | is_nothrow_move_assignable<allocator_type>::value) || |
726 | allocator_traits<allocator_type>::is_always_equal::value); |
727 | |
728 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI forward_list& operator=(initializer_list<value_type> __il); |
729 | |
730 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void assign(initializer_list<value_type> __il); |
731 | # endif // _LIBCPP_CXX03_LANG |
732 | |
733 | // ~forward_list() = default; |
734 | |
735 | template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0> |
736 | _LIBCPP_CONSTEXPR_SINCE_CXX26 void _LIBCPP_HIDE_FROM_ABI assign(_InputIterator __f, _InputIterator __l); |
737 | |
738 | # if _LIBCPP_STD_VER >= 23 |
739 | template <_ContainerCompatibleRange<_Tp> _Range> |
740 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void assign_range(_Range&& __range) { |
741 | __assign_with_sentinel(ranges::begin(__range), ranges::end(__range)); |
742 | } |
743 | # endif |
744 | |
745 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void assign(size_type __n, const value_type& __v); |
746 | |
747 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT { |
748 | return allocator_type(this->__alloc_); |
749 | } |
750 | |
751 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { |
752 | return iterator(__base::__before_begin()->__next_); |
753 | } |
754 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { |
755 | return const_iterator(__base::__before_begin()->__next_); |
756 | } |
757 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return iterator(nullptr); } |
758 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { |
759 | return const_iterator(nullptr); |
760 | } |
761 | |
762 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { |
763 | return const_iterator(__base::__before_begin()->__next_); |
764 | } |
765 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { |
766 | return const_iterator(nullptr); |
767 | } |
768 | |
769 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator before_begin() _NOEXCEPT { |
770 | return iterator(__base::__before_begin()); |
771 | } |
772 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator before_begin() const _NOEXCEPT { |
773 | return const_iterator(__base::__before_begin()); |
774 | } |
775 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator cbefore_begin() const _NOEXCEPT { |
776 | return const_iterator(__base::__before_begin()); |
777 | } |
778 | |
779 | [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { |
780 | return __base::__before_begin()->__next_ == nullptr; |
781 | } |
782 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { |
783 | return std::min<size_type>(__node_traits::max_size(this->__alloc_), numeric_limits<difference_type>::max()); |
784 | } |
785 | |
786 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI reference front() { |
787 | _LIBCPP_ASSERT_NON_NULL(!empty(), "forward_list::front called on an empty list" ); |
788 | return __base::__before_begin()->__next_->__get_value(); |
789 | } |
790 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_reference front() const { |
791 | _LIBCPP_ASSERT_NON_NULL(!empty(), "forward_list::front called on an empty list" ); |
792 | return __base::__before_begin()->__next_->__get_value(); |
793 | } |
794 | |
795 | # ifndef _LIBCPP_CXX03_LANG |
796 | # if _LIBCPP_STD_VER >= 17 |
797 | template <class... _Args> |
798 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI reference emplace_front(_Args&&... __args); |
799 | # else |
800 | template <class... _Args> |
801 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void emplace_front(_Args&&... __args); |
802 | # endif |
803 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void push_front(value_type&& __v); |
804 | # endif // _LIBCPP_CXX03_LANG |
805 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void push_front(const value_type& __v); |
806 | |
807 | # if _LIBCPP_STD_VER >= 23 |
808 | template <_ContainerCompatibleRange<_Tp> _Range> |
809 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void prepend_range(_Range&& __range) { |
810 | insert_range_after(cbefore_begin(), std::forward<_Range>(__range)); |
811 | } |
812 | # endif |
813 | |
814 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void pop_front(); |
815 | |
816 | # ifndef _LIBCPP_CXX03_LANG |
817 | template <class... _Args> |
818 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator emplace_after(const_iterator __p, _Args&&... __args); |
819 | |
820 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator insert_after(const_iterator __p, value_type&& __v); |
821 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator |
822 | insert_after(const_iterator __p, initializer_list<value_type> __il) { |
823 | return insert_after(__p, __il.begin(), __il.end()); |
824 | } |
825 | # endif // _LIBCPP_CXX03_LANG |
826 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator insert_after(const_iterator __p, const value_type& __v); |
827 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator |
828 | insert_after(const_iterator __p, size_type __n, const value_type& __v) { |
829 | return __insert_after(__p, __n, __v); |
830 | } |
831 | template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0> |
832 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator |
833 | insert_after(const_iterator __p, _InputIterator __f, _InputIterator __l); |
834 | |
835 | # if _LIBCPP_STD_VER >= 23 |
836 | template <_ContainerCompatibleRange<_Tp> _Range> |
837 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator |
838 | insert_range_after(const_iterator __position, _Range&& __range) { |
839 | return __insert_after_with_sentinel(__position, ranges::begin(__range), ranges::end(__range)); |
840 | } |
841 | # endif |
842 | |
843 | template <class _InputIterator, class _Sentinel> |
844 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator |
845 | __insert_after_with_sentinel(const_iterator __p, _InputIterator __f, _Sentinel __l); |
846 | |
847 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator erase_after(const_iterator __p); |
848 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator erase_after(const_iterator __f, const_iterator __l); |
849 | |
850 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void swap(forward_list& __x) |
851 | # if _LIBCPP_STD_VER >= 14 |
852 | _NOEXCEPT |
853 | # else |
854 | _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>) |
855 | # endif |
856 | { |
857 | __base::swap(__x); |
858 | } |
859 | |
860 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void resize(size_type __n); |
861 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void resize(size_type __n, const value_type& __v); |
862 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __base::clear(); } |
863 | |
864 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void splice_after(const_iterator __p, forward_list&& __x); |
865 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void |
866 | splice_after(const_iterator __p, forward_list&& __x, const_iterator __i); |
867 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void |
868 | splice_after(const_iterator __p, forward_list&& __x, const_iterator __f, const_iterator __l); |
869 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void splice_after(const_iterator __p, forward_list& __x); |
870 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void |
871 | splice_after(const_iterator __p, forward_list& __x, const_iterator __i); |
872 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void |
873 | splice_after(const_iterator __p, forward_list& __x, const_iterator __f, const_iterator __l); |
874 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __remove_return_type remove(const value_type& __v); |
875 | template <class _Predicate> |
876 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __remove_return_type remove_if(_Predicate __pred); |
877 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __remove_return_type unique() { return unique(__equal_to()); } |
878 | template <class _BinaryPredicate> |
879 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __remove_return_type unique(_BinaryPredicate __binary_pred); |
880 | # ifndef _LIBCPP_CXX03_LANG |
881 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void merge(forward_list&& __x) { merge(__x, __less<>()); } |
882 | template <class _Compare> |
883 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void merge(forward_list&& __x, _Compare __comp) { |
884 | merge(__x, std::move(__comp)); |
885 | } |
886 | # endif // _LIBCPP_CXX03_LANG |
887 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void merge(forward_list& __x) { merge(__x, __less<>()); } |
888 | template <class _Compare> |
889 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void merge(forward_list& __x, _Compare __comp); |
890 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void sort() { sort(__less<>()); } |
891 | template <class _Compare> |
892 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void sort(_Compare __comp); |
893 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void reverse() _NOEXCEPT; |
894 | |
895 | private: |
896 | # ifndef _LIBCPP_CXX03_LANG |
897 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __move_assign(forward_list& __x, true_type) |
898 | _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value); |
899 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __move_assign(forward_list& __x, false_type); |
900 | # endif // _LIBCPP_CXX03_LANG |
901 | |
902 | template <class _Iter, class _Sent> |
903 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __assign_with_sentinel(_Iter __f, _Sent __l); |
904 | |
905 | template <class... _Args> |
906 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator |
907 | __insert_after(const_iterator __p, size_type __n, _Args&&... __args); |
908 | |
909 | template <class _Compare> |
910 | _LIBCPP_CONSTEXPR_SINCE_CXX26 static _LIBCPP_HIDE_FROM_ABI __node_pointer |
911 | __merge(__node_pointer __f1, __node_pointer __f2, _Compare& __comp); |
912 | |
913 | // TODO: Make this _LIBCPP_HIDE_FROM_ABI |
914 | template <class _Compare> |
915 | _LIBCPP_CONSTEXPR_SINCE_CXX26 static _LIBCPP_HIDDEN __node_pointer |
916 | __sort(__node_pointer __f, difference_type __sz, _Compare& __comp); |
917 | }; |
918 | |
919 | # if _LIBCPP_STD_VER >= 17 |
920 | template <class _InputIterator, |
921 | class _Alloc = allocator<__iter_value_type<_InputIterator>>, |
922 | class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, |
923 | class = enable_if_t<__is_allocator<_Alloc>::value> > |
924 | forward_list(_InputIterator, _InputIterator) -> forward_list<__iter_value_type<_InputIterator>, _Alloc>; |
925 | |
926 | template <class _InputIterator, |
927 | class _Alloc, |
928 | class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, |
929 | class = enable_if_t<__is_allocator<_Alloc>::value> > |
930 | forward_list(_InputIterator, _InputIterator, _Alloc) -> forward_list<__iter_value_type<_InputIterator>, _Alloc>; |
931 | # endif |
932 | |
933 | # if _LIBCPP_STD_VER >= 23 |
934 | template <ranges::input_range _Range, |
935 | class _Alloc = allocator<ranges::range_value_t<_Range>>, |
936 | class = enable_if_t<__is_allocator<_Alloc>::value> > |
937 | forward_list(from_range_t, _Range&&, _Alloc = _Alloc()) -> forward_list<ranges::range_value_t<_Range>, _Alloc>; |
938 | # endif |
939 | |
940 | template <class _Tp, class _Alloc> |
941 | _LIBCPP_CONSTEXPR_SINCE_CXX26 inline forward_list<_Tp, _Alloc>::forward_list(const allocator_type& __a) : __base(__a) {} |
942 | |
943 | template <class _Tp, class _Alloc> |
944 | _LIBCPP_CONSTEXPR_SINCE_CXX26 forward_list<_Tp, _Alloc>::forward_list(size_type __n) { |
945 | if (__n > 0) { |
946 | for (__begin_node_pointer __p = __base::__before_begin(); __n > 0; |
947 | --__n, __p = std::__static_fancy_pointer_cast<__begin_node_pointer>(__p->__next_)) { |
948 | __p->__next_ = this->__create_node(/* next = */ nullptr); |
949 | } |
950 | } |
951 | } |
952 | |
953 | # if _LIBCPP_STD_VER >= 14 |
954 | template <class _Tp, class _Alloc> |
955 | _LIBCPP_CONSTEXPR_SINCE_CXX26 forward_list<_Tp, _Alloc>::forward_list(size_type __n, const allocator_type& __base_alloc) |
956 | : __base(__base_alloc) { |
957 | if (__n > 0) { |
958 | for (__begin_node_pointer __p = __base::__before_begin(); __n > 0; |
959 | --__n, __p = std::__static_fancy_pointer_cast<__begin_node_pointer>(__p->__next_)) { |
960 | __p->__next_ = this->__create_node(/* next = */ nullptr); |
961 | } |
962 | } |
963 | } |
964 | # endif |
965 | |
966 | template <class _Tp, class _Alloc> |
967 | _LIBCPP_CONSTEXPR_SINCE_CXX26 forward_list<_Tp, _Alloc>::forward_list(size_type __n, const value_type& __v) { |
968 | insert_after(cbefore_begin(), __n, __v); |
969 | } |
970 | |
971 | template <class _Tp, class _Alloc> |
972 | template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> > |
973 | _LIBCPP_CONSTEXPR_SINCE_CXX26 forward_list<_Tp, _Alloc>::forward_list(_InputIterator __f, _InputIterator __l) { |
974 | insert_after(cbefore_begin(), __f, __l); |
975 | } |
976 | |
977 | template <class _Tp, class _Alloc> |
978 | template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> > |
979 | _LIBCPP_CONSTEXPR_SINCE_CXX26 |
980 | forward_list<_Tp, _Alloc>::forward_list(_InputIterator __f, _InputIterator __l, const allocator_type& __a) |
981 | : __base(__a) { |
982 | insert_after(cbefore_begin(), __f, __l); |
983 | } |
984 | |
985 | template <class _Tp, class _Alloc> |
986 | _LIBCPP_CONSTEXPR_SINCE_CXX26 forward_list<_Tp, _Alloc>::forward_list(const forward_list& __x) |
987 | : __base(__node_traits::select_on_container_copy_construction(__x.__alloc_)) { |
988 | insert_after(cbefore_begin(), __x.begin(), __x.end()); |
989 | } |
990 | |
991 | template <class _Tp, class _Alloc> |
992 | _LIBCPP_CONSTEXPR_SINCE_CXX26 |
993 | forward_list<_Tp, _Alloc>::forward_list(const forward_list& __x, const __type_identity_t<allocator_type>& __a) |
994 | : __base(__a) { |
995 | insert_after(cbefore_begin(), __x.begin(), __x.end()); |
996 | } |
997 | |
998 | template <class _Tp, class _Alloc> |
999 | _LIBCPP_CONSTEXPR_SINCE_CXX26 forward_list<_Tp, _Alloc>& forward_list<_Tp, _Alloc>::operator=(const forward_list& __x) { |
1000 | if (this != std::addressof(__x)) { |
1001 | __base::__copy_assign_alloc(__x); |
1002 | assign(__x.begin(), __x.end()); |
1003 | } |
1004 | return *this; |
1005 | } |
1006 | |
1007 | # ifndef _LIBCPP_CXX03_LANG |
1008 | template <class _Tp, class _Alloc> |
1009 | _LIBCPP_CONSTEXPR_SINCE_CXX26 |
1010 | forward_list<_Tp, _Alloc>::forward_list(forward_list&& __x, const __type_identity_t<allocator_type>& __a) |
1011 | : __base(std::move(__x), __a) { |
1012 | if (this->__alloc_ != __x.__alloc_) { |
1013 | typedef move_iterator<iterator> _Ip; |
1014 | insert_after(cbefore_begin(), _Ip(__x.begin()), _Ip(__x.end())); |
1015 | } |
1016 | } |
1017 | |
1018 | template <class _Tp, class _Alloc> |
1019 | _LIBCPP_CONSTEXPR_SINCE_CXX26 forward_list<_Tp, _Alloc>::forward_list(initializer_list<value_type> __il) { |
1020 | insert_after(cbefore_begin(), __il.begin(), __il.end()); |
1021 | } |
1022 | |
1023 | template <class _Tp, class _Alloc> |
1024 | _LIBCPP_CONSTEXPR_SINCE_CXX26 |
1025 | forward_list<_Tp, _Alloc>::forward_list(initializer_list<value_type> __il, const allocator_type& __a) |
1026 | : __base(__a) { |
1027 | insert_after(cbefore_begin(), __il.begin(), __il.end()); |
1028 | } |
1029 | |
1030 | template <class _Tp, class _Alloc> |
1031 | _LIBCPP_CONSTEXPR_SINCE_CXX26 void forward_list<_Tp, _Alloc>::__move_assign(forward_list& __x, true_type) |
1032 | _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) { |
1033 | clear(); |
1034 | __base::__move_assign_alloc(__x); |
1035 | __base::__before_begin()->__next_ = __x.__before_begin()->__next_; |
1036 | __x.__before_begin()->__next_ = nullptr; |
1037 | } |
1038 | |
1039 | template <class _Tp, class _Alloc> |
1040 | _LIBCPP_CONSTEXPR_SINCE_CXX26 void forward_list<_Tp, _Alloc>::__move_assign(forward_list& __x, false_type) { |
1041 | if (this->__alloc_ == __x.__alloc_) |
1042 | __move_assign(__x, true_type()); |
1043 | else { |
1044 | typedef move_iterator<iterator> _Ip; |
1045 | assign(_Ip(__x.begin()), _Ip(__x.end())); |
1046 | } |
1047 | } |
1048 | |
1049 | template <class _Tp, class _Alloc> |
1050 | _LIBCPP_CONSTEXPR_SINCE_CXX26 inline forward_list<_Tp, _Alloc>& |
1051 | forward_list<_Tp, _Alloc>::operator=(forward_list&& __x) noexcept( |
1052 | (__node_traits::propagate_on_container_move_assignment::value && |
1053 | is_nothrow_move_assignable<allocator_type>::value) || |
1054 | allocator_traits<allocator_type>::is_always_equal::value) { |
1055 | __move_assign(__x, integral_constant<bool, __node_traits::propagate_on_container_move_assignment::value>()); |
1056 | return *this; |
1057 | } |
1058 | |
1059 | template <class _Tp, class _Alloc> |
1060 | _LIBCPP_CONSTEXPR_SINCE_CXX26 inline forward_list<_Tp, _Alloc>& |
1061 | forward_list<_Tp, _Alloc>::operator=(initializer_list<value_type> __il) { |
1062 | assign(__il.begin(), __il.end()); |
1063 | return *this; |
1064 | } |
1065 | |
1066 | # endif // _LIBCPP_CXX03_LANG |
1067 | |
1068 | template <class _Tp, class _Alloc> |
1069 | template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> > |
1070 | _LIBCPP_CONSTEXPR_SINCE_CXX26 void forward_list<_Tp, _Alloc>::assign(_InputIterator __f, _InputIterator __l) { |
1071 | __assign_with_sentinel(__f, __l); |
1072 | } |
1073 | |
1074 | template <class _Tp, class _Alloc> |
1075 | template <class _Iter, class _Sent> |
1076 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void |
1077 | forward_list<_Tp, _Alloc>::__assign_with_sentinel(_Iter __f, _Sent __l) { |
1078 | iterator __i = before_begin(); |
1079 | iterator __j = std::next(__i); |
1080 | iterator __e = end(); |
1081 | for (; __j != __e && __f != __l; ++__i, (void)++__j, ++__f) |
1082 | *__j = *__f; |
1083 | if (__j == __e) |
1084 | __insert_after_with_sentinel(__i, std::move(__f), std::move(__l)); |
1085 | else |
1086 | erase_after(__i, __e); |
1087 | } |
1088 | |
1089 | template <class _Tp, class _Alloc> |
1090 | _LIBCPP_CONSTEXPR_SINCE_CXX26 void forward_list<_Tp, _Alloc>::assign(size_type __n, const value_type& __v) { |
1091 | iterator __i = before_begin(); |
1092 | iterator __j = std::next(__i); |
1093 | iterator __e = end(); |
1094 | for (; __j != __e && __n > 0; --__n, ++__i, ++__j) |
1095 | *__j = __v; |
1096 | if (__j == __e) |
1097 | insert_after(__i, __n, __v); |
1098 | else |
1099 | erase_after(__i, __e); |
1100 | } |
1101 | |
1102 | # ifndef _LIBCPP_CXX03_LANG |
1103 | |
1104 | template <class _Tp, class _Alloc> |
1105 | _LIBCPP_CONSTEXPR_SINCE_CXX26 inline void forward_list<_Tp, _Alloc>::assign(initializer_list<value_type> __il) { |
1106 | assign(__il.begin(), __il.end()); |
1107 | } |
1108 | |
1109 | template <class _Tp, class _Alloc> |
1110 | template <class... _Args> |
1111 | _LIBCPP_CONSTEXPR_SINCE_CXX26 |
1112 | # if _LIBCPP_STD_VER >= 17 |
1113 | typename forward_list<_Tp, _Alloc>::reference |
1114 | # else |
1115 | void |
1116 | # endif |
1117 | forward_list<_Tp, _Alloc>::emplace_front(_Args&&... __args) { |
1118 | __base::__before_begin()->__next_ = |
1119 | this->__create_node(/* next = */ __base::__before_begin()->__next_, std::forward<_Args>(__args)...); |
1120 | # if _LIBCPP_STD_VER >= 17 |
1121 | return __base::__before_begin()->__next_->__get_value(); |
1122 | # endif |
1123 | } |
1124 | |
1125 | template <class _Tp, class _Alloc> |
1126 | _LIBCPP_CONSTEXPR_SINCE_CXX26 void forward_list<_Tp, _Alloc>::push_front(value_type&& __v) { |
1127 | __base::__before_begin()->__next_ = |
1128 | this->__create_node(/* next = */ __base::__before_begin()->__next_, std::move(__v)); |
1129 | } |
1130 | |
1131 | # endif // _LIBCPP_CXX03_LANG |
1132 | |
1133 | template <class _Tp, class _Alloc> |
1134 | _LIBCPP_CONSTEXPR_SINCE_CXX26 void forward_list<_Tp, _Alloc>::push_front(const value_type& __v) { |
1135 | __base::__before_begin()->__next_ = this->__create_node(/* next = */ __base::__before_begin()->__next_, __v); |
1136 | } |
1137 | |
1138 | template <class _Tp, class _Alloc> |
1139 | _LIBCPP_CONSTEXPR_SINCE_CXX26 void forward_list<_Tp, _Alloc>::pop_front() { |
1140 | _LIBCPP_ASSERT_NON_NULL(!empty(), "forward_list::pop_front called on an empty list" ); |
1141 | __node_pointer __p = __base::__before_begin()->__next_; |
1142 | __base::__before_begin()->__next_ = __p->__next_; |
1143 | this->__delete_node(__p); |
1144 | } |
1145 | |
1146 | # ifndef _LIBCPP_CXX03_LANG |
1147 | |
1148 | template <class _Tp, class _Alloc> |
1149 | template <class... _Args> |
1150 | _LIBCPP_CONSTEXPR_SINCE_CXX26 typename forward_list<_Tp, _Alloc>::iterator |
1151 | forward_list<_Tp, _Alloc>::emplace_after(const_iterator __p, _Args&&... __args) { |
1152 | __begin_node_pointer const __r = __p.__ptr_; |
1153 | __r->__next_ = this->__create_node(/* next = */ __r->__next_, std::forward<_Args>(__args)...); |
1154 | return iterator(__r->__next_); |
1155 | } |
1156 | |
1157 | template <class _Tp, class _Alloc> |
1158 | _LIBCPP_CONSTEXPR_SINCE_CXX26 typename forward_list<_Tp, _Alloc>::iterator |
1159 | forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, value_type&& __v) { |
1160 | __begin_node_pointer const __r = __p.__ptr_; |
1161 | __r->__next_ = this->__create_node(/* next = */ __r->__next_, std::move(__v)); |
1162 | return iterator(__r->__next_); |
1163 | } |
1164 | |
1165 | # endif // _LIBCPP_CXX03_LANG |
1166 | |
1167 | template <class _Tp, class _Alloc> |
1168 | _LIBCPP_CONSTEXPR_SINCE_CXX26 typename forward_list<_Tp, _Alloc>::iterator |
1169 | forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, const value_type& __v) { |
1170 | __begin_node_pointer const __r = __p.__ptr_; |
1171 | __r->__next_ = this->__create_node(/* next = */ __r->__next_, __v); |
1172 | return iterator(__r->__next_); |
1173 | } |
1174 | |
1175 | template <class _Tp, class _Alloc> |
1176 | template <class... _Args> |
1177 | _LIBCPP_CONSTEXPR_SINCE_CXX26 typename forward_list<_Tp, _Alloc>::iterator |
1178 | forward_list<_Tp, _Alloc>::__insert_after(const_iterator __p, size_type __n, _Args&&... __args) { |
1179 | __begin_node_pointer __r = __p.__ptr_; |
1180 | if (__n > 0) { |
1181 | __node_pointer __first = this->__create_node(/* next = */ nullptr, std::forward<_Args>(__args)...); |
1182 | __node_pointer __last = __first; |
1183 | # if _LIBCPP_HAS_EXCEPTIONS |
1184 | try { |
1185 | # endif // _LIBCPP_HAS_EXCEPTIONS |
1186 | for (--__n; __n != 0; --__n, __last = __last->__next_) { |
1187 | __last->__next_ = this->__create_node(/* next = */ nullptr, std::forward<_Args>(__args)...); |
1188 | } |
1189 | # if _LIBCPP_HAS_EXCEPTIONS |
1190 | } catch (...) { |
1191 | while (__first != nullptr) { |
1192 | __node_pointer __next = __first->__next_; |
1193 | this->__delete_node(__first); |
1194 | __first = __next; |
1195 | } |
1196 | throw; |
1197 | } |
1198 | # endif // _LIBCPP_HAS_EXCEPTIONS |
1199 | __last->__next_ = __r->__next_; |
1200 | __r->__next_ = __first; |
1201 | __r = std::__static_fancy_pointer_cast<__begin_node_pointer>(__last); |
1202 | } |
1203 | return iterator(__r); |
1204 | } |
1205 | |
1206 | template <class _Tp, class _Alloc> |
1207 | template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> > |
1208 | _LIBCPP_CONSTEXPR_SINCE_CXX26 typename forward_list<_Tp, _Alloc>::iterator |
1209 | forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, _InputIterator __f, _InputIterator __l) { |
1210 | return __insert_after_with_sentinel(__p, std::move(__f), std::move(__l)); |
1211 | } |
1212 | |
1213 | template <class _Tp, class _Alloc> |
1214 | template <class _InputIterator, class _Sentinel> |
1215 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI typename forward_list<_Tp, _Alloc>::iterator |
1216 | forward_list<_Tp, _Alloc>::__insert_after_with_sentinel(const_iterator __p, _InputIterator __f, _Sentinel __l) { |
1217 | __begin_node_pointer __r = __p.__ptr_; |
1218 | |
1219 | if (__f != __l) { |
1220 | __node_pointer __first = this->__create_node(/* next = */ nullptr, *__f); |
1221 | __node_pointer __last = __first; |
1222 | |
1223 | # if _LIBCPP_HAS_EXCEPTIONS |
1224 | try { |
1225 | # endif // _LIBCPP_HAS_EXCEPTIONS |
1226 | for (++__f; __f != __l; ++__f, ((void)(__last = __last->__next_))) { |
1227 | __last->__next_ = this->__create_node(/* next = */ nullptr, *__f); |
1228 | } |
1229 | # if _LIBCPP_HAS_EXCEPTIONS |
1230 | } catch (...) { |
1231 | while (__first != nullptr) { |
1232 | __node_pointer __next = __first->__next_; |
1233 | this->__delete_node(__first); |
1234 | __first = __next; |
1235 | } |
1236 | throw; |
1237 | } |
1238 | # endif // _LIBCPP_HAS_EXCEPTIONS |
1239 | |
1240 | __last->__next_ = __r->__next_; |
1241 | __r->__next_ = __first; |
1242 | __r = std::__static_fancy_pointer_cast<__begin_node_pointer>(__last); |
1243 | } |
1244 | |
1245 | return iterator(__r); |
1246 | } |
1247 | |
1248 | template <class _Tp, class _Alloc> |
1249 | _LIBCPP_CONSTEXPR_SINCE_CXX26 typename forward_list<_Tp, _Alloc>::iterator |
1250 | forward_list<_Tp, _Alloc>::erase_after(const_iterator __f) { |
1251 | __begin_node_pointer __p = __f.__ptr_; |
1252 | __node_pointer __n = __p->__next_; |
1253 | __p->__next_ = __n->__next_; |
1254 | this->__delete_node(__n); |
1255 | return iterator(__p->__next_); |
1256 | } |
1257 | |
1258 | template <class _Tp, class _Alloc> |
1259 | _LIBCPP_CONSTEXPR_SINCE_CXX26 typename forward_list<_Tp, _Alloc>::iterator |
1260 | forward_list<_Tp, _Alloc>::erase_after(const_iterator __f, const_iterator __l) { |
1261 | __node_pointer __e = std::__static_fancy_pointer_cast<__node_pointer>(__l.__ptr_); |
1262 | if (__f != __l) { |
1263 | __begin_node_pointer __bp = __f.__ptr_; |
1264 | |
1265 | __node_pointer __n = __bp->__next_; |
1266 | if (__n != __e) { |
1267 | __bp->__next_ = __e; |
1268 | do { |
1269 | __node_pointer __tmp = __n->__next_; |
1270 | this->__delete_node(__n); |
1271 | __n = __tmp; |
1272 | } while (__n != __e); |
1273 | } |
1274 | } |
1275 | return iterator(__e); |
1276 | } |
1277 | |
1278 | template <class _Tp, class _Alloc> |
1279 | _LIBCPP_CONSTEXPR_SINCE_CXX26 void forward_list<_Tp, _Alloc>::resize(size_type __n) { |
1280 | size_type __sz = 0; |
1281 | iterator __p = before_begin(); |
1282 | iterator __i = begin(); |
1283 | iterator __e = end(); |
1284 | for (; __i != __e && __sz < __n; ++__p, ++__i, ++__sz) |
1285 | ; |
1286 | if (__i != __e) |
1287 | erase_after(__p, __e); |
1288 | else |
1289 | __insert_after(__p, __n - __sz); |
1290 | } |
1291 | |
1292 | template <class _Tp, class _Alloc> |
1293 | _LIBCPP_CONSTEXPR_SINCE_CXX26 void forward_list<_Tp, _Alloc>::resize(size_type __n, const value_type& __v) { |
1294 | size_type __sz = 0; |
1295 | iterator __p = before_begin(); |
1296 | iterator __i = begin(); |
1297 | iterator __e = end(); |
1298 | for (; __i != __e && __sz < __n; ++__p, ++__i, ++__sz) |
1299 | ; |
1300 | if (__i != __e) |
1301 | erase_after(__p, __e); |
1302 | else |
1303 | __insert_after(__p, __n - __sz, __v); |
1304 | } |
1305 | |
1306 | template <class _Tp, class _Alloc> |
1307 | _LIBCPP_CONSTEXPR_SINCE_CXX26 void forward_list<_Tp, _Alloc>::splice_after(const_iterator __p, forward_list& __x) { |
1308 | if (!__x.empty()) { |
1309 | if (__p.__ptr_->__next_ != nullptr) { |
1310 | const_iterator __lm1 = __x.before_begin(); |
1311 | while (__lm1.__ptr_->__next_ != nullptr) |
1312 | ++__lm1; |
1313 | __lm1.__ptr_->__next_ = __p.__ptr_->__next_; |
1314 | } |
1315 | __p.__ptr_->__next_ = __x.__before_begin()->__next_; |
1316 | __x.__before_begin()->__next_ = nullptr; |
1317 | } |
1318 | } |
1319 | |
1320 | template <class _Tp, class _Alloc> |
1321 | _LIBCPP_CONSTEXPR_SINCE_CXX26 void |
1322 | forward_list<_Tp, _Alloc>::splice_after(const_iterator __p, forward_list& /*__other*/, const_iterator __i) { |
1323 | const_iterator __lm1 = std::next(__i); |
1324 | if (__p != __i && __p != __lm1) { |
1325 | __i.__ptr_->__next_ = __lm1.__ptr_->__next_; |
1326 | __lm1.__ptr_->__next_ = __p.__ptr_->__next_; |
1327 | __p.__ptr_->__next_ = std::__static_fancy_pointer_cast<__node_pointer>(__lm1.__ptr_); |
1328 | } |
1329 | } |
1330 | |
1331 | template <class _Tp, class _Alloc> |
1332 | _LIBCPP_CONSTEXPR_SINCE_CXX26 void forward_list<_Tp, _Alloc>::splice_after( |
1333 | const_iterator __p, forward_list& /*__other*/, const_iterator __f, const_iterator __l) { |
1334 | if (__f != __l && __p != __f) { |
1335 | const_iterator __lm1 = __f; |
1336 | while (__lm1.__ptr_->__next_ != __l.__ptr_) |
1337 | ++__lm1; |
1338 | if (__f != __lm1) { |
1339 | __lm1.__ptr_->__next_ = __p.__ptr_->__next_; |
1340 | __p.__ptr_->__next_ = __f.__ptr_->__next_; |
1341 | __f.__ptr_->__next_ = std::__static_fancy_pointer_cast<__node_pointer>(__l.__ptr_); |
1342 | } |
1343 | } |
1344 | } |
1345 | |
1346 | template <class _Tp, class _Alloc> |
1347 | _LIBCPP_CONSTEXPR_SINCE_CXX26 inline _LIBCPP_HIDE_FROM_ABI void |
1348 | forward_list<_Tp, _Alloc>::splice_after(const_iterator __p, forward_list&& __x) { |
1349 | splice_after(__p, __x); |
1350 | } |
1351 | |
1352 | template <class _Tp, class _Alloc> |
1353 | _LIBCPP_CONSTEXPR_SINCE_CXX26 inline _LIBCPP_HIDE_FROM_ABI void |
1354 | forward_list<_Tp, _Alloc>::splice_after(const_iterator __p, forward_list&& __x, const_iterator __i) { |
1355 | splice_after(__p, __x, __i); |
1356 | } |
1357 | |
1358 | template <class _Tp, class _Alloc> |
1359 | _LIBCPP_CONSTEXPR_SINCE_CXX26 inline _LIBCPP_HIDE_FROM_ABI void forward_list<_Tp, _Alloc>::splice_after( |
1360 | const_iterator __p, forward_list&& __x, const_iterator __f, const_iterator __l) { |
1361 | splice_after(__p, __x, __f, __l); |
1362 | } |
1363 | |
1364 | template <class _Tp, class _Alloc> |
1365 | _LIBCPP_CONSTEXPR_SINCE_CXX26 typename forward_list<_Tp, _Alloc>::__remove_return_type |
1366 | forward_list<_Tp, _Alloc>::remove(const value_type& __v) { |
1367 | forward_list<_Tp, _Alloc> __deleted_nodes(get_allocator()); // collect the nodes we're removing |
1368 | typename forward_list<_Tp, _Alloc>::size_type __count_removed = 0; |
1369 | const iterator __e = end(); |
1370 | for (iterator __i = before_begin(); __i.__ptr_->__next_ != nullptr;) { |
1371 | if (__i.__ptr_->__next_->__get_value() == __v) { |
1372 | ++__count_removed; |
1373 | iterator __j = std::next(__i, 2); |
1374 | for (; __j != __e && *__j == __v; ++__j) |
1375 | ++__count_removed; |
1376 | __deleted_nodes.splice_after(__deleted_nodes.before_begin(), *this, __i, __j); |
1377 | if (__j == __e) |
1378 | break; |
1379 | __i = __j; |
1380 | } else |
1381 | ++__i; |
1382 | } |
1383 | |
1384 | return (__remove_return_type)__count_removed; |
1385 | } |
1386 | |
1387 | template <class _Tp, class _Alloc> |
1388 | template <class _Predicate> |
1389 | _LIBCPP_CONSTEXPR_SINCE_CXX26 typename forward_list<_Tp, _Alloc>::__remove_return_type |
1390 | forward_list<_Tp, _Alloc>::remove_if(_Predicate __pred) { |
1391 | forward_list<_Tp, _Alloc> __deleted_nodes(get_allocator()); // collect the nodes we're removing |
1392 | typename forward_list<_Tp, _Alloc>::size_type __count_removed = 0; |
1393 | const iterator __e = end(); |
1394 | for (iterator __i = before_begin(); __i.__ptr_->__next_ != nullptr;) { |
1395 | if (__pred(__i.__ptr_->__next_->__get_value())) { |
1396 | ++__count_removed; |
1397 | iterator __j = std::next(__i, 2); |
1398 | for (; __j != __e && __pred(*__j); ++__j) |
1399 | ++__count_removed; |
1400 | __deleted_nodes.splice_after(__deleted_nodes.before_begin(), *this, __i, __j); |
1401 | if (__j == __e) |
1402 | break; |
1403 | __i = __j; |
1404 | } else |
1405 | ++__i; |
1406 | } |
1407 | |
1408 | return (__remove_return_type)__count_removed; |
1409 | } |
1410 | |
1411 | template <class _Tp, class _Alloc> |
1412 | template <class _BinaryPredicate> |
1413 | _LIBCPP_CONSTEXPR_SINCE_CXX26 typename forward_list<_Tp, _Alloc>::__remove_return_type |
1414 | forward_list<_Tp, _Alloc>::unique(_BinaryPredicate __binary_pred) { |
1415 | forward_list<_Tp, _Alloc> __deleted_nodes(get_allocator()); // collect the nodes we're removing |
1416 | typename forward_list<_Tp, _Alloc>::size_type __count_removed = 0; |
1417 | for (iterator __i = begin(), __e = end(); __i != __e;) { |
1418 | iterator __j = std::next(__i); |
1419 | for (; __j != __e && __binary_pred(*__i, *__j); ++__j) |
1420 | ++__count_removed; |
1421 | if (__i.__ptr_->__next_ != std::__static_fancy_pointer_cast<__node_pointer>(__j.__ptr_)) |
1422 | __deleted_nodes.splice_after(__deleted_nodes.before_begin(), *this, __i, __j); |
1423 | __i = __j; |
1424 | } |
1425 | |
1426 | return (__remove_return_type)__count_removed; |
1427 | } |
1428 | |
1429 | template <class _Tp, class _Alloc> |
1430 | template <class _Compare> |
1431 | _LIBCPP_CONSTEXPR_SINCE_CXX26 void forward_list<_Tp, _Alloc>::merge(forward_list& __x, _Compare __comp) { |
1432 | if (this != std::addressof(__x)) { |
1433 | __base::__before_begin()->__next_ = |
1434 | __merge(__base::__before_begin()->__next_, __x.__before_begin()->__next_, __comp); |
1435 | __x.__before_begin()->__next_ = nullptr; |
1436 | } |
1437 | } |
1438 | |
1439 | template <class _Tp, class _Alloc> |
1440 | template <class _Compare> |
1441 | _LIBCPP_CONSTEXPR_SINCE_CXX26 typename forward_list<_Tp, _Alloc>::__node_pointer |
1442 | forward_list<_Tp, _Alloc>::__merge(__node_pointer __f1, __node_pointer __f2, _Compare& __comp) { |
1443 | if (__f1 == nullptr) |
1444 | return __f2; |
1445 | if (__f2 == nullptr) |
1446 | return __f1; |
1447 | __node_pointer __r; |
1448 | if (__comp(__f2->__get_value(), __f1->__get_value())) { |
1449 | __node_pointer __t = __f2; |
1450 | while (__t->__next_ != nullptr && __comp(__t->__next_->__get_value(), __f1->__get_value())) |
1451 | __t = __t->__next_; |
1452 | __r = __f2; |
1453 | __f2 = __t->__next_; |
1454 | __t->__next_ = __f1; |
1455 | } else |
1456 | __r = __f1; |
1457 | __node_pointer __p = __f1; |
1458 | __f1 = __f1->__next_; |
1459 | while (__f1 != nullptr && __f2 != nullptr) { |
1460 | if (__comp(__f2->__get_value(), __f1->__get_value())) { |
1461 | __node_pointer __t = __f2; |
1462 | while (__t->__next_ != nullptr && __comp(__t->__next_->__get_value(), __f1->__get_value())) |
1463 | __t = __t->__next_; |
1464 | __p->__next_ = __f2; |
1465 | __f2 = __t->__next_; |
1466 | __t->__next_ = __f1; |
1467 | } |
1468 | __p = __f1; |
1469 | __f1 = __f1->__next_; |
1470 | } |
1471 | if (__f2 != nullptr) |
1472 | __p->__next_ = __f2; |
1473 | return __r; |
1474 | } |
1475 | |
1476 | template <class _Tp, class _Alloc> |
1477 | template <class _Compare> |
1478 | _LIBCPP_CONSTEXPR_SINCE_CXX26 inline void forward_list<_Tp, _Alloc>::sort(_Compare __comp) { |
1479 | __base::__before_begin()->__next_ = __sort(__base::__before_begin()->__next_, std::distance(begin(), end()), __comp); |
1480 | } |
1481 | |
1482 | template <class _Tp, class _Alloc> |
1483 | template <class _Compare> |
1484 | _LIBCPP_CONSTEXPR_SINCE_CXX26 typename forward_list<_Tp, _Alloc>::__node_pointer |
1485 | forward_list<_Tp, _Alloc>::__sort(__node_pointer __f1, difference_type __sz, _Compare& __comp) { |
1486 | switch (__sz) { |
1487 | case 0: |
1488 | case 1: |
1489 | return __f1; |
1490 | case 2: |
1491 | if (__comp(__f1->__next_->__get_value(), __f1->__get_value())) { |
1492 | __node_pointer __t = __f1->__next_; |
1493 | __t->__next_ = __f1; |
1494 | __f1->__next_ = nullptr; |
1495 | __f1 = __t; |
1496 | } |
1497 | return __f1; |
1498 | } |
1499 | difference_type __sz1 = __sz / 2; |
1500 | difference_type __sz2 = __sz - __sz1; |
1501 | __node_pointer __t = std::__static_fancy_pointer_cast<__node_pointer>(std::next(iterator(__f1), __sz1 - 1).__ptr_); |
1502 | __node_pointer __f2 = __t->__next_; |
1503 | __t->__next_ = nullptr; |
1504 | return __merge(__sort(__f1, __sz1, __comp), __sort(__f2, __sz2, __comp), __comp); |
1505 | } |
1506 | |
1507 | template <class _Tp, class _Alloc> |
1508 | _LIBCPP_CONSTEXPR_SINCE_CXX26 void forward_list<_Tp, _Alloc>::reverse() _NOEXCEPT { |
1509 | __node_pointer __p = __base::__before_begin()->__next_; |
1510 | if (__p != nullptr) { |
1511 | __node_pointer __f = __p->__next_; |
1512 | __p->__next_ = nullptr; |
1513 | while (__f != nullptr) { |
1514 | __node_pointer __t = __f->__next_; |
1515 | __f->__next_ = __p; |
1516 | __p = __f; |
1517 | __f = __t; |
1518 | } |
1519 | __base::__before_begin()->__next_ = __p; |
1520 | } |
1521 | } |
1522 | |
1523 | template <class _Tp, class _Alloc> |
1524 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI bool |
1525 | operator==(const forward_list<_Tp, _Alloc>& __x, const forward_list<_Tp, _Alloc>& __y) { |
1526 | typedef forward_list<_Tp, _Alloc> _Cp; |
1527 | typedef typename _Cp::const_iterator _Ip; |
1528 | _Ip __ix = __x.begin(); |
1529 | _Ip __ex = __x.end(); |
1530 | _Ip __iy = __y.begin(); |
1531 | _Ip __ey = __y.end(); |
1532 | for (; __ix != __ex && __iy != __ey; ++__ix, ++__iy) |
1533 | if (!(*__ix == *__iy)) |
1534 | return false; |
1535 | return (__ix == __ex) == (__iy == __ey); |
1536 | } |
1537 | |
1538 | # if _LIBCPP_STD_VER <= 17 |
1539 | |
1540 | template <class _Tp, class _Alloc> |
1541 | _LIBCPP_CONSTEXPR_SINCE_CXX26 inline _LIBCPP_HIDE_FROM_ABI bool |
1542 | operator!=(const forward_list<_Tp, _Alloc>& __x, const forward_list<_Tp, _Alloc>& __y) { |
1543 | return !(__x == __y); |
1544 | } |
1545 | |
1546 | template <class _Tp, class _Alloc> |
1547 | _LIBCPP_CONSTEXPR_SINCE_CXX26 inline _LIBCPP_HIDE_FROM_ABI bool |
1548 | operator<(const forward_list<_Tp, _Alloc>& __x, const forward_list<_Tp, _Alloc>& __y) { |
1549 | return std::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end()); |
1550 | } |
1551 | |
1552 | template <class _Tp, class _Alloc> |
1553 | _LIBCPP_CONSTEXPR_SINCE_CXX26 inline _LIBCPP_HIDE_FROM_ABI bool |
1554 | operator>(const forward_list<_Tp, _Alloc>& __x, const forward_list<_Tp, _Alloc>& __y) { |
1555 | return __y < __x; |
1556 | } |
1557 | |
1558 | template <class _Tp, class _Alloc> |
1559 | _LIBCPP_CONSTEXPR_SINCE_CXX26 inline _LIBCPP_HIDE_FROM_ABI bool |
1560 | operator>=(const forward_list<_Tp, _Alloc>& __x, const forward_list<_Tp, _Alloc>& __y) { |
1561 | return !(__x < __y); |
1562 | } |
1563 | |
1564 | template <class _Tp, class _Alloc> |
1565 | _LIBCPP_CONSTEXPR_SINCE_CXX26 inline _LIBCPP_HIDE_FROM_ABI bool |
1566 | operator<=(const forward_list<_Tp, _Alloc>& __x, const forward_list<_Tp, _Alloc>& __y) { |
1567 | return !(__y < __x); |
1568 | } |
1569 | |
1570 | # else // #if _LIBCPP_STD_VER <= 17 |
1571 | |
1572 | template <class _Tp, class _Allocator> |
1573 | _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __synth_three_way_result<_Tp> |
1574 | operator<=>(const forward_list<_Tp, _Allocator>& __x, const forward_list<_Tp, _Allocator>& __y) { |
1575 | return std::lexicographical_compare_three_way(__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way); |
1576 | } |
1577 | |
1578 | # endif // #if _LIBCPP_STD_VER <= 17 |
1579 | |
1580 | template <class _Tp, class _Alloc> |
1581 | _LIBCPP_CONSTEXPR_SINCE_CXX26 inline _LIBCPP_HIDE_FROM_ABI void |
1582 | swap(forward_list<_Tp, _Alloc>& __x, forward_list<_Tp, _Alloc>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { |
1583 | __x.swap(__y); |
1584 | } |
1585 | |
1586 | # if _LIBCPP_STD_VER >= 20 |
1587 | template <class _Tp, class _Allocator, class _Predicate> |
1588 | _LIBCPP_CONSTEXPR_SINCE_CXX26 inline _LIBCPP_HIDE_FROM_ABI typename forward_list<_Tp, _Allocator>::size_type |
1589 | erase_if(forward_list<_Tp, _Allocator>& __c, _Predicate __pred) { |
1590 | return __c.remove_if(__pred); |
1591 | } |
1592 | |
1593 | template <class _Tp, class _Allocator, class _Up> |
1594 | _LIBCPP_CONSTEXPR_SINCE_CXX26 inline _LIBCPP_HIDE_FROM_ABI typename forward_list<_Tp, _Allocator>::size_type |
1595 | erase(forward_list<_Tp, _Allocator>& __c, const _Up& __v) { |
1596 | return std::erase_if(__c, [&](const auto& __elem) -> bool { return __elem == __v; }); |
1597 | } |
1598 | # endif |
1599 | |
1600 | template <class _Tp, class _Allocator> |
1601 | struct __container_traits<forward_list<_Tp, _Allocator> > { |
1602 | // http://eel.is/c++draft/container.reqmts |
1603 | // Unless otherwise specified (see [associative.reqmts.except], [unord.req.except], [deque.modifiers], |
1604 | // [inplace.vector.modifiers], and [vector.modifiers]) all container types defined in this Clause meet the following |
1605 | // additional requirements: |
1606 | // - If an exception is thrown by an insert() or emplace() function while inserting a single element, that |
1607 | // function has no effects. |
1608 | static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee = true; |
1609 | |
1610 | static _LIBCPP_CONSTEXPR const bool __reservable = false; |
1611 | }; |
1612 | |
1613 | _LIBCPP_END_NAMESPACE_STD |
1614 | |
1615 | # if _LIBCPP_STD_VER >= 17 |
1616 | _LIBCPP_BEGIN_NAMESPACE_STD |
1617 | namespace pmr { |
1618 | template <class _ValueT> |
1619 | using forward_list _LIBCPP_AVAILABILITY_PMR = std::forward_list<_ValueT, polymorphic_allocator<_ValueT>>; |
1620 | } // namespace pmr |
1621 | _LIBCPP_END_NAMESPACE_STD |
1622 | # endif |
1623 | |
1624 | _LIBCPP_POP_MACROS |
1625 | |
1626 | # if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 |
1627 | # include <algorithm> |
1628 | # include <atomic> |
1629 | # include <concepts> |
1630 | # include <cstdint> |
1631 | # include <cstdlib> |
1632 | # include <cstring> |
1633 | # include <functional> |
1634 | # include <iosfwd> |
1635 | # include <iterator> |
1636 | # include <stdexcept> |
1637 | # include <type_traits> |
1638 | # include <typeinfo> |
1639 | # endif |
1640 | #endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) |
1641 | |
1642 | #endif // _LIBCPP_FORWARD_LIST |
1643 | |