]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/bits/forward_list.tcc
4.cc: New.
[thirdparty/gcc.git] / libstdc++-v3 / include / bits / forward_list.tcc
CommitLineData
3a63c9cd
ESR
1// <forward_list.tcc> -*- C++ -*-
2
1e3ca17d 3// Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
3a63c9cd
ESR
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
748086b7 8// Free Software Foundation; either version 3, or (at your option)
3a63c9cd
ESR
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
748086b7
JJ
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
3a63c9cd
ESR
24
25/** @file forward_list.tcc
26 * This is a Standard C++ Library header.
27 */
28
29#ifndef _FORWARD_LIST_TCC
30#define _FORWARD_LIST_TCC 1
31
32_GLIBCXX_BEGIN_NAMESPACE(std)
33
3a63c9cd
ESR
34 template<typename _Tp, typename _Alloc>
35 _Fwd_list_base<_Tp, _Alloc>::
36 _Fwd_list_base(const _Fwd_list_base& __lst, const _Alloc& __a)
37 : _M_impl(__a)
38 {
39 this->_M_impl._M_head._M_next = 0;
97ffcedf
PC
40 _Fwd_list_node_base* __to = &this->_M_impl._M_head;
41 _Node* __curr = static_cast<_Node*>(__lst._M_impl._M_head._M_next);
42
3a63c9cd 43 while (__curr)
1b32e4e5
BW
44 {
45 __to->_M_next = _M_create_node(__curr->_M_value);
46 __to = __to->_M_next;
97ffcedf 47 __curr = static_cast<_Node*>(__curr->_M_next);
1b32e4e5 48 }
3a63c9cd
ESR
49 }
50
2a7ee2f9
PC
51 template<typename _Tp, typename _Alloc>
52 template<typename... _Args>
97ffcedf 53 _Fwd_list_node_base*
2a7ee2f9
PC
54 _Fwd_list_base<_Tp, _Alloc>::
55 _M_insert_after(const_iterator __pos, _Args&&... __args)
56 {
97ffcedf
PC
57 _Fwd_list_node_base* __to
58 = const_cast<_Fwd_list_node_base*>(__pos._M_node);
59 _Node* __thing = _M_create_node(std::forward<_Args>(__args)...);
1b32e4e5
BW
60 __thing->_M_next = __to->_M_next;
61 __to->_M_next = __thing;
97ffcedf 62 return __to->_M_next;
2a7ee2f9
PC
63 }
64
3a63c9cd 65 template<typename _Tp, typename _Alloc>
33913cfa 66 void
3a63c9cd 67 _Fwd_list_base<_Tp, _Alloc>::
97ffcedf 68 _M_erase_after(_Fwd_list_node_base* __pos)
3a63c9cd 69 {
97ffcedf 70 _Node* __curr = static_cast<_Node*>(__pos->_M_next);
33913cfa
PC
71 __pos->_M_next = __curr->_M_next;
72 _M_get_Node_allocator().destroy(__curr);
73 _M_put_node(__curr);
3a63c9cd
ESR
74 }
75
76 template<typename _Tp, typename _Alloc>
33913cfa 77 void
3a63c9cd 78 _Fwd_list_base<_Tp, _Alloc>::
97ffcedf
PC
79 _M_erase_after(_Fwd_list_node_base* __pos,
80 _Fwd_list_node_base* __last)
3a63c9cd 81 {
97ffcedf 82 _Node* __curr = static_cast<_Node*>(__pos->_M_next);
33913cfa 83 while (__curr != __last)
1b32e4e5 84 {
97ffcedf
PC
85 _Node* __temp = __curr;
86 __curr = static_cast<_Node*>(__curr->_M_next);
1b32e4e5
BW
87 _M_get_Node_allocator().destroy(__temp);
88 _M_put_node(__temp);
1b32e4e5 89 }
33913cfa 90 __pos->_M_next = __last;
3a63c9cd
ESR
91 }
92
e73d6fe8 93 // Called by the range constructor to implement [23.1.1]/9
3a63c9cd
ESR
94 template<typename _Tp, typename _Alloc>
95 template<typename _InputIterator>
e73d6fe8 96 void
3a63c9cd 97 forward_list<_Tp, _Alloc>::
e73d6fe8
ESR
98 _M_initialize_dispatch(_InputIterator __first, _InputIterator __last,
99 __false_type)
3a63c9cd 100 {
97ffcedf 101 _Node_base* __to = &this->_M_impl._M_head;
27caad2e 102 for (; __first != __last; ++__first)
3a63c9cd 103 {
27caad2e 104 __to->_M_next = this->_M_create_node(*__first);
3a63c9cd 105 __to = __to->_M_next;
3a63c9cd
ESR
106 }
107 }
108
e73d6fe8
ESR
109 // Called by forward_list(n,v,a), and the range constructor
110 // when it turns out to be the same thing.
3a63c9cd 111 template<typename _Tp, typename _Alloc>
e73d6fe8 112 void
3a63c9cd 113 forward_list<_Tp, _Alloc>::
e73d6fe8 114 _M_fill_initialize(size_type __n, const value_type& __value)
3a63c9cd 115 {
97ffcedf 116 _Node_base* __to = &this->_M_impl._M_head;
dc2cf706 117 for (; __n; --__n)
e73d6fe8
ESR
118 {
119 __to->_M_next = this->_M_create_node(__value);
120 __to = __to->_M_next;
121 }
3a63c9cd
ESR
122 }
123
1e3ca17d 124 template<typename _Tp, typename _Alloc>
dc2cf706 125 void
1e3ca17d 126 forward_list<_Tp, _Alloc>::
dc2cf706 127 _M_default_initialize(size_type __n)
1e3ca17d 128 {
97ffcedf 129 _Node_base* __to = &this->_M_impl._M_head;
dc2cf706 130 for (; __n; --__n)
1e3ca17d
PC
131 {
132 __to->_M_next = this->_M_create_node();
133 __to = __to->_M_next;
134 }
135 }
136
3a63c9cd
ESR
137 template<typename _Tp, typename _Alloc>
138 forward_list<_Tp, _Alloc>&
139 forward_list<_Tp, _Alloc>::
140 operator=(const forward_list& __list)
141 {
142 if (&__list != this)
1b32e4e5
BW
143 {
144 iterator __prev1 = before_begin();
145 iterator __curr1 = begin();
146 iterator __last1 = end();
147 const_iterator __first2 = __list.cbegin();
148 const_iterator __last2 = __list.cend();
149 while (__curr1 != __last1 && __first2 != __last2)
150 {
151 *__curr1 = *__first2;
152 ++__prev1;
153 ++__curr1;
154 ++__first2;
155 }
156 if (__first2 == __last2)
157 erase_after(__prev1, __last1);
158 else
159 insert_after(__prev1, __first2, __last2);
160 }
3a63c9cd
ESR
161 return *this;
162 }
163
dc2cf706
PC
164 template<typename _Tp, typename _Alloc>
165 void
166 forward_list<_Tp, _Alloc>::
167 _M_default_insert_after(const_iterator __pos, size_type __n)
168 {
169 const_iterator __saved_pos = __pos;
170 __try
171 {
172 for (; __n; --__n)
173 __pos = emplace_after(__pos);
174 }
175 __catch(...)
176 {
177 erase_after(__saved_pos, ++__pos);
178 __throw_exception_again;
179 }
180 }
181
1e3ca17d
PC
182 template<typename _Tp, typename _Alloc>
183 void
184 forward_list<_Tp, _Alloc>::
185 resize(size_type __sz)
186 {
187 iterator __k = before_begin();
188
189 size_type __len = 0;
190 while (__k._M_next() != end() && __len < __sz)
191 {
192 ++__k;
193 ++__len;
194 }
195 if (__len == __sz)
196 erase_after(__k, end());
197 else
dc2cf706 198 _M_default_insert_after(__k, __sz - __len);
1e3ca17d
PC
199 }
200
3a63c9cd
ESR
201 template<typename _Tp, typename _Alloc>
202 void
203 forward_list<_Tp, _Alloc>::
204 resize(size_type __sz, value_type __val)
205 {
206 iterator __k = before_begin();
207
208 size_type __len = 0;
209 while (__k._M_next() != end() && __len < __sz)
1b32e4e5
BW
210 {
211 ++__k;
212 ++__len;
213 }
3a63c9cd 214 if (__len == __sz)
1b32e4e5 215 erase_after(__k, end());
3a63c9cd 216 else
1b32e4e5 217 insert_after(__k, __sz - __len, __val);
3a63c9cd
ESR
218 }
219
2a7ee2f9 220 template<typename _Tp, typename _Alloc>
16920896 221 typename forward_list<_Tp, _Alloc>::iterator
2a7ee2f9 222 forward_list<_Tp, _Alloc>::
16920896 223 _M_splice_after(const_iterator __pos, forward_list&& __list)
2a7ee2f9 224 {
16920896
PC
225 _Node_base* __tmp = const_cast<_Node_base*>(__pos._M_node);
226 iterator __before = __list.before_begin();
227 return iterator(__tmp->_M_transfer_after(__before._M_node));
2a7ee2f9
PC
228 }
229
230 template<typename _Tp, typename _Alloc>
231 void
232 forward_list<_Tp, _Alloc>::
16920896 233 splice_after(const_iterator __pos, forward_list&&,
1b32e4e5 234 const_iterator __before, const_iterator __last)
2a7ee2f9 235 {
97ffcedf
PC
236 _Node_base* __tmp = const_cast<_Node_base*>(__pos._M_node);
237 __tmp->_M_transfer_after(const_cast<_Node_base*>(__before._M_node),
238 const_cast<_Node_base*>(__last._M_node));
2a7ee2f9
PC
239 }
240
16920896
PC
241 template<typename _Tp, typename _Alloc>
242 typename forward_list<_Tp, _Alloc>::iterator
243 forward_list<_Tp, _Alloc>::
244 insert_after(const_iterator __pos, size_type __n, const _Tp& __val)
245 {
246 if (__n)
247 {
248 forward_list __tmp(__n, __val, this->_M_get_Node_allocator());
249 return _M_splice_after(__pos, std::move(__tmp));
250 }
251 else
252 return iterator(const_cast<_Node_base*>(__pos._M_node));
253 }
254
255 template<typename _Tp, typename _Alloc>
256 template<typename _InputIterator>
257 typename forward_list<_Tp, _Alloc>::iterator
258 forward_list<_Tp, _Alloc>::
259 insert_after(const_iterator __pos,
260 _InputIterator __first, _InputIterator __last)
261 {
262 forward_list __tmp(__first, __last, this->_M_get_Node_allocator());
263 if (!__tmp.empty())
264 return _M_splice_after(__pos, std::move(__tmp));
265 else
266 return iterator(const_cast<_Node_base*>(__pos._M_node));
267 }
268
269 template<typename _Tp, typename _Alloc>
270 typename forward_list<_Tp, _Alloc>::iterator
271 forward_list<_Tp, _Alloc>::
272 insert_after(const_iterator __pos, std::initializer_list<_Tp> __il)
273 {
274 if (__il.size())
275 {
276 forward_list __tmp(__il, this->_M_get_Node_allocator());
277 return _M_splice_after(__pos, std::move(__tmp));
278 }
279 else
280 return iterator(const_cast<_Node_base*>(__pos._M_node));
281 }
282
3a63c9cd
ESR
283 template<typename _Tp, typename _Alloc>
284 void
285 forward_list<_Tp, _Alloc>::
286 remove(const _Tp& __val)
287 {
97ffcedf 288 _Node* __curr = static_cast<_Node*>(&this->_M_impl._M_head);
afb767b4
PC
289 _Node* __extra = 0;
290
291 while (_Node* __tmp = static_cast<_Node*>(__curr->_M_next))
1b32e4e5 292 {
afb767b4
PC
293 if (__tmp->_M_value == __val)
294 {
295 if (std::__addressof(__tmp->_M_value)
296 != std::__addressof(__val))
297 {
298 this->_M_erase_after(__curr);
299 continue;
300 }
301 else
302 __extra = __curr;
303 }
304 __curr = static_cast<_Node*>(__curr->_M_next);
1b32e4e5 305 }
afb767b4
PC
306
307 if (__extra)
308 this->_M_erase_after(__extra);
3a63c9cd
ESR
309 }
310
311 template<typename _Tp, typename _Alloc>
312 template<typename _Pred>
313 void
314 forward_list<_Tp, _Alloc>::
315 remove_if(_Pred __pred)
316 {
97ffcedf 317 _Node* __curr = static_cast<_Node*>(&this->_M_impl._M_head);
afb767b4 318 while (_Node* __tmp = static_cast<_Node*>(__curr->_M_next))
1b32e4e5 319 {
afb767b4 320 if (__pred(__tmp->_M_value))
1b32e4e5
BW
321 this->_M_erase_after(__curr);
322 else
97ffcedf 323 __curr = static_cast<_Node*>(__curr->_M_next);
1b32e4e5 324 }
3a63c9cd
ESR
325 }
326
3a63c9cd
ESR
327 template<typename _Tp, typename _Alloc>
328 template<typename _BinPred>
329 void
330 forward_list<_Tp, _Alloc>::
331 unique(_BinPred __binary_pred)
332 {
333 iterator __first = begin();
334 iterator __last = end();
335 if (__first == __last)
1b32e4e5 336 return;
3a63c9cd
ESR
337 iterator __next = __first;
338 while (++__next != __last)
1b32e4e5
BW
339 {
340 if (__binary_pred(*__first, *__next))
341 erase_after(__first);
342 else
343 __first = __next;
344 __next = __first;
345 }
3a63c9cd
ESR
346 }
347
348 template<typename _Tp, typename _Alloc>
349 template<typename _Comp>
350 void
351 forward_list<_Tp, _Alloc>::
352 merge(forward_list&& __list, _Comp __comp)
353 {
97ffcedf 354 _Node_base* __node = &this->_M_impl._M_head;
3a63c9cd
ESR
355 while (__node->_M_next && __list._M_impl._M_head._M_next)
356 {
97ffcedf 357 if (__comp(static_cast<_Node*>
1b32e4e5 358 (__list._M_impl._M_head._M_next)->_M_value,
97ffcedf 359 static_cast<_Node*>
1b32e4e5 360 (__node->_M_next)->_M_value))
3a63c9cd
ESR
361 __node->_M_transfer_after(&__list._M_impl._M_head,
362 __list._M_impl._M_head._M_next);
363 __node = __node->_M_next;
364 }
365 if (__list._M_impl._M_head._M_next)
366 {
367 __node->_M_next = __list._M_impl._M_head._M_next;
368 __list._M_impl._M_head._M_next = 0;
369 }
370 }
371
2a7ee2f9
PC
372 template<typename _Tp, typename _Alloc>
373 bool
374 operator==(const forward_list<_Tp, _Alloc>& __lx,
375 const forward_list<_Tp, _Alloc>& __ly)
376 {
377 // We don't have size() so we need to walk through both lists
378 // making sure both iterators are valid.
919e5c5e
PC
379 auto __ix = __lx.cbegin();
380 auto __iy = __ly.cbegin();
2a7ee2f9
PC
381 while (__ix != __lx.cend() && __iy != __ly.cend())
382 {
383 if (*__ix != *__iy)
384 return false;
385 ++__ix;
386 ++__iy;
387 }
388 if (__ix == __lx.cend() && __iy == __ly.cend())
389 return true;
390 else
391 return false;
392 }
393
fc52f99d
PC
394 template<typename _Tp, class _Alloc>
395 template<typename _Comp>
396 void
397 forward_list<_Tp, _Alloc>::
398 sort(_Comp __comp)
399 {
fc52f99d 400 // If `next' is 0, return immediately.
97ffcedf 401 _Node* __list = static_cast<_Node*>(this->_M_impl._M_head._M_next);
fc52f99d
PC
402 if (!__list)
403 return;
404
405 unsigned long __insize = 1;
406
407 while (1)
408 {
97ffcedf 409 _Node* __p = __list;
fc52f99d 410 __list = 0;
97ffcedf 411 _Node* __tail = 0;
fc52f99d
PC
412
413 // Count number of merges we do in this pass.
414 unsigned long __nmerges = 0;
415
416 while (__p)
417 {
418 ++__nmerges;
419 // There exists a merge to be done.
420 // Step `insize' places along from p.
97ffcedf 421 _Node* __q = __p;
fc52f99d
PC
422 unsigned long __psize = 0;
423 for (unsigned long __i = 0; __i < __insize; ++__i)
424 {
425 ++__psize;
97ffcedf 426 __q = static_cast<_Node*>(__q->_M_next);
fc52f99d
PC
427 if (!__q)
428 break;
429 }
430
431 // If q hasn't fallen off end, we have two lists to merge.
432 unsigned long __qsize = __insize;
433
434 // Now we have two lists; merge them.
435 while (__psize > 0 || (__qsize > 0 && __q))
436 {
437 // Decide whether next node of merge comes from p or q.
97ffcedf 438 _Node* __e;
fc52f99d
PC
439 if (__psize == 0)
440 {
441 // p is empty; e must come from q.
442 __e = __q;
97ffcedf 443 __q = static_cast<_Node*>(__q->_M_next);
fc52f99d
PC
444 --__qsize;
445 }
446 else if (__qsize == 0 || !__q)
447 {
448 // q is empty; e must come from p.
449 __e = __p;
97ffcedf 450 __p = static_cast<_Node*>(__p->_M_next);
fc52f99d
PC
451 --__psize;
452 }
453 else if (__comp(__p->_M_value, __q->_M_value))
454 {
455 // First node of p is lower; e must come from p.
456 __e = __p;
97ffcedf 457 __p = static_cast<_Node*>(__p->_M_next);
fc52f99d
PC
458 --__psize;
459 }
460 else
461 {
462 // First node of q is lower; e must come from q.
463 __e = __q;
97ffcedf 464 __q = static_cast<_Node*>(__q->_M_next);
fc52f99d
PC
465 --__qsize;
466 }
467
468 // Add the next node to the merged list.
469 if (__tail)
470 __tail->_M_next = __e;
471 else
472 __list = __e;
473 __tail = __e;
474 }
475
476 // Now p has stepped `insize' places along, and q has too.
477 __p = __q;
478 }
479 __tail->_M_next = 0;
480
481 // If we have done only one merge, we're finished.
482 // Allow for nmerges == 0, the empty list case.
483 if (__nmerges <= 1)
484 {
485 this->_M_impl._M_head._M_next = __list;
486 return;
487 }
488
489 // Otherwise repeat, merging lists twice the size.
490 __insize *= 2;
491 }
492 }
493
3a63c9cd
ESR
494_GLIBCXX_END_NAMESPACE // namespace std
495
496#endif /* _FORWARD_LIST_TCC */
497