Library of Assembled Shared Sources
slist.inl
Go to the documentation of this file.
1/** @file
2 * @author Bram de Greve (bram@cocamware.com)
3 * @author Tom De Muer (tom@cocamware.com)
4 *
5 * *** BEGIN LICENSE INFORMATION ***
6 *
7 * The contents of this file are subject to the Common Public Attribution License
8 * Version 1.0 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://lass.sourceforge.net/cpal-license. The License is based on the
11 * Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover
12 * use of software over a computer network and provide for limited attribution for
13 * the Original Developer. In addition, Exhibit A has been modified to be consistent
14 * with Exhibit B.
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
17 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
18 * language governing rights and limitations under the License.
19 *
20 * The Original Code is LASS - Library of Assembled Shared Sources.
21 *
22 * The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
23 * The Original Developer is the Initial Developer.
24 *
25 * All portions of the code written by the Initial Developer are:
26 * Copyright (C) 2004-2011 the Initial Developer.
27 * All Rights Reserved.
28 *
29 * Contributor(s):
30 *
31 * Alternatively, the contents of this file may be used under the terms of the
32 * GNU General Public License Version 2 or later (the GPL), in which case the
33 * provisions of GPL are applicable instead of those above. If you wish to allow use
34 * of your version of this file only under the terms of the GPL and not to allow
35 * others to use your version of this file under the CPAL, indicate your decision by
36 * deleting the provisions above and replace them with the notice and other
37 * provisions required by the GPL License. If you do not delete the provisions above,
38 * a recipient may use your version of this file under either the CPAL or the GPL.
39 *
40 * *** END LICENSE INFORMATION ***
41 */
42
43#include "../meta/is_integral.h"
44
45namespace lass
46{
47namespace stde
48{
49
50namespace impl
51{
52
53/** @internal
54 */
55struct slist_traits
56{
57 template <typename Container, typename T>
58 static void push(Container& container, const T& value)
59 {
60 container.push_front(value);
61 }
62 template <typename Container>
63 static void temp_to_output(Container& temp, Container& output)
64 {
65 temp.swap(output);
66 }
67};
68
69}
70
71
72
73// --- public --------------------------------------------------------------------------------------
74
75/** Creates an empty list, using the provided allocator
76 *
77 * @param allocator to be used as memory model, defaults to @c Alloc().
78 *
79 * @b complexity: O(1)
80 */
81template <typename T, class Alloc>
82slist<T, Alloc>::slist(const Alloc& allocator):
83 Alloc(allocator)
84{
85 head_.next = 0;
86}
87
88
89
90/** Creates an list with @a n elements - each of which is a copy of @a value - and an allocator.
91 *
92 * @param n is the number of copies of @a value to put in the list.
93 * @param value will be used to copy construct all of the @a n elements of the list,
94 * defaults to @c T().
95 * @param allocator to be used as memory model, defaults to @c Alloc().
96 *
97 * @b complexity: O(N) with N = @a n.
98 */
99template <typename T, class Alloc>
100slist<T, Alloc>::slist(size_type n, const T& value, const Alloc& allocator):
101 Alloc(allocator)
102{
103 head_.next = 0;
104 insert_after(before_begin(), n, value);
105}
106
107
108
109/** creates a list with as elements a copy of a range, and an allocator.
110 *
111 * @param first iterator to first element of range to be copied in list.
112 * @param last iterator to position after the last element to be copied in list.
113 * @a last must be forward reachable from @a first.
114 * @param allocator to be used as memory model, defaults to @c Alloc().
115 *
116 * @b complexity: O(N) with N = <tt>std::distance(first, last)</tt>.
117 */
118template <typename T, class Alloc>
119template <typename InputIterator>
120slist<T, Alloc>::slist(InputIterator first, InputIterator last, const Alloc& allocator):
121 Alloc(allocator)
122{
123 head_.next = 0;
124 insert_after(before_begin(), first, last);
125}
126
127
128
129/** copies an entire list and its elements and allocator.
130 *
131 * @param other the list to be copied
132 *
133 * @b complexity: O(N) with N = @c other.size()
134 */
135template <typename T, class Alloc>
137 Alloc(other.get_allocator())
138{
139 head_.next = 0;
140 insert_after(before_begin(), other.begin(), other.end());
141}
142
143
144
145/** destroys all elements and frees memory.
146 *
147 * @b complexity: O(N) with N = @c this->size()
148 */
149template <typename T, class Alloc>
151{
152 while (head_.next)
154 unlink_and_destroy_after(&head_);
156}
159
160/** replace @c *this by a copy of @a other.
161 *
162 * @param other list to be copied
164 * @b complexity: O(N1) + O(N2) with N1 = @c this->size() and N2 = @c other.size().
165 */
166template <typename T, class Alloc>
169 swap(other);
170 return *this;
171}
175/** replace @c *this by a list copied from a range.
176 *
177 * @param first iterator to first element of range to be copied in list.
178 * @param last iterator to position after the last element to be copied in list.
179 * @a last must be forward reachable from @a first.
181 * @b complexity: O(N1) + O(N2) with N1 = @c this->size() and
182 * N2 = <tt>std::distance(first, last)</tt>.
183 */
184template <typename T, class Alloc>
185template <typename ForwardIterator>
186void slist<T, Alloc>::assign(ForwardIterator first, ForwardIterator last)
188 slist<T, Alloc> temp(first, last, get_allocator());
189 swap(temp);
190}
191
194/** replace @c *this by a list with @a n copies of @a value
195 *
196 * @param n is the number of copies of @a value to put in the list.
197 * @param value will be used to copy construct all of the @a n elements of the list.
199 * @b complexity: O(N1) + O(N2) with N1 = @c this->size() and N2 = @a n.
200 */
201template <typename T, class Alloc>
202void slist<T, Alloc>::assign(size_type n, const T& value)
203{
205 swap(temp);
207
210/** returns the memory model of the list.
211 *
212 * @b complexity: O(1)
213 */
214template <typename T, class Alloc>
215typename slist<T, Alloc>::allocator_type
218 return *static_cast<const allocator_type*>(this);
221
223/** returns an iterator to the first element of the list.
224 *
225 * @b complexity: O(1)
226 */
227template <typename T, class Alloc>
228typename slist<T, Alloc>::iterator
230{
231 return iterator(head_.next);
232}
233
234
235
236/** returns an iterator to the first element of the list.
237 *
238 * @b complexity: O(1)
239 */
240template <typename T, class Alloc>
241typename slist<T, Alloc>::const_iterator
243{
244 return const_iterator(head_.next);
245}
246
247
248
249/** returns an iterator for the position after the last element of the list.
250 *
251 * @b complexity: O(1)
252 */
253template <typename T, class Alloc>
254typename slist<T, Alloc>::iterator
256{
257 return iterator(0);
258}
259
260
261
262/** returns an iterator for the position after the last element of the list.
263 *
264 * @b complexity: O(1)
265 */
266template <typename T, class Alloc>
267typename slist<T, Alloc>::const_iterator
269{
270 return const_iterator(0);
271}
272
273
274
275/** returns an iterator for the position before the first element of the list.
276 * This iterator is not dereferencable! It's only an iterator for which the next one is
277 * @c this->begin(). Use this one in methods like @c insert_after and @c erase_after when you want
278 * the method to affect on the first element in the list. Using @c begin() would fail for this
279 * purpose the element after @c this->begin() is already the second in the list.
280 *
281 * @b complexity: O(1)
282 */
283template <typename T, class Alloc>
284typename slist<T, Alloc>::iterator
286{
287 return iterator(&head_);
288}
289
290
291
292/** returns an iterator for the position before the first element of the list.
293 * This iterator is not dereferencable! It's only an iterator for which the next one is
294 * @c this->begin(). Use this one in methods like @c insert_after and @c erase_after when you want
295 * the method to affect on the first element in the list. Using @c begin() would fail for this
296 * purpose the element after @c this->begin() is already the second in the list.
297 *
298 * @b complexity: O(1)
299 */
300template <typename T, class Alloc>
301typename slist<T, Alloc>::const_iterator
303{
304 return const_iterator(&head_);
305}
306
307
308
309/** return the iterator that sits @a position and start searching for it from @a start.
310 * Equivalent to <tt>this->prior(position, this->before_begin())</tt>.
311 *
312 * @param position must be valid in @c *this and should not be @c this->before_begin()
313 *
314 * @b complexity: O(N) with N = <tt>std::distance(this->begin(), position)</tt>
315 */
316template <typename T, class Alloc>
317typename slist<T, Alloc>::iterator
318slist<T, Alloc>::prior(iterator position) const
319{
320 return prior(position, const_cast<slist<T, Alloc>*>(this)->before_begin());
321}
322
323
324
325/** return the iterator that sits @a position and start searching for it from @a start.
326 * Equivalent to <tt>this->prior(position, this->before_begin())</tt>.
327 *
328 * @param position must be valid in @c *this and should not be @c this->before_begin()
329 *
330 * @b complexity: O(N) with N = <tt>std::distance(this->begin(), position)</tt>
331 */
332template <typename T, class Alloc>
333typename slist<T, Alloc>::const_iterator
334slist<T, Alloc>::prior(const_iterator position) const
335{
336 return prior(position, before_begin());
337}
338
339
340
341/** return the iterator that sits @a position and start searching for it from @a start.
342 * The method scans linearly all iterators from @a start until it find the one for which the next
343 * one is @a position. It returns the same result as @c std::prior(position) would have returned
344 * if the iterator had support for the decrement operation.
345 *
346 * @param position must be valid in @c *this and should not be @c this->before_begin()
347 * @param start must be a valid iterator in @c [this->begin(),position)
348 *
349 * @b complexity: O(N) with N = <tt>std::distance(start, position)</tt>
350 */
351template <typename T, class Alloc>
352typename slist<T, Alloc>::iterator
353slist<T, Alloc>::prior(iterator position, iterator start) const
354{
355 iterator result = start;
356 while (result.node_->next != position.node_)
357 {
358 LASS_ASSERT(result.node_->next);
359 ++result;
360 }
361 return result;
362}
363
364
365
366/** return the iterator that sits @a position and start searching for it from @a start.
367 * The method scans linearly all iterators from @a start until it find the one for which the next
368 * one is @a position. It returns the same result as @c std::prior(position) would have returned
369 * if the iterator had support for the decrement operation.
370 *
371 * @param position must be valid in @c *this and should not be @c this->before_begin()
372 * @param start must be a valid iterator in @c [this->begin(),position)
373 *
374 * @b complexity: O(N) with N = <tt>std::distance(start, position)</tt>
375 */
376template <typename T, class Alloc>
377typename slist<T, Alloc>::const_iterator
378slist<T, Alloc>::prior(const_iterator position, const_iterator start) const
379{
380 const_iterator result = start;
381 while (result.node_->next != position.node_)
382 {
383 LASS_ASSERT(result.node_->next);
384 ++result;
385 }
386 return result;
387}
388
389
390
391/** returns wether the list is empty.
392 * Is semantically identical to <tt>this->size() == 0</tt>, but it is a lot faster.
393 * So use it whenever you can ... even to do the dishes.
394 *
395 * @b complexity: O(1)
396 */
397template <typename T, class Alloc>
399{
400 return head_.next == 0;
401}
402
403
404
405/** returns the N, the number of elements in the list.
406 *
407 * @b complexity: O(N) with N = @c this->size().
408 */
409template <typename T, class Alloc>
410typename slist<T, Alloc>::size_type
412{
413 size_type n = 0;
414 for (node_base_t* i = head_.next; i != 0; i = i->next)
415 {
416 ++n;
417 }
418 return n;
419}
420
421
422
423/** returns a @e very rough estimation on what's the maximum number of elements you can
424 * ever have in an @c slist.
425 *
426 * Frankly, we don't know this number, so we return the highest number we know of =)
427 *
428 * @b complexity: O(1)
429 */
430template <typename T, class Alloc>
431typename slist<T, Alloc>::size_type
433{
434 // if anyone knows something better, please feel free to do so [Bramz]
435 //
436 return size_type(-1);
437}
438
439
440
441/** at the end of the list, inserts copies of @a value or erases elements so that list size is @a n.
442 *
443 * @param n the size of the list after inserting or erasing elements.
444 * @param value if the list must grow, copies of @a value are inserted at the end.
445 * Defaults to T().
446 *
447 * @b complexity: O(N) with N = @a n.
448 */
449template <typename T, class Alloc>
450void slist<T, Alloc>::resize(size_type n, const T& value)
451{
452 node_base_t* i = &head_;
453 while (i->next && n)
454 {
455 --n;
456 i = i->next;
457 }
458 if (n)
459 {
460 insert_after(iterator(i), n, value);
461 }
462 else
463 {
464 while (i->next)
465 {
466 unlink_and_destroy_after(i);
467 }
468 }
469}
470
471
472
473/** returns reference to first element in list.
474 *
475 * @c *this must not be empty. There's no check on wheter the first element exists.
476 * It's semantically equivalent to @c *this->begin()
477 *
478 * @b complexity: O(1)
479 */
480template <typename T, class Alloc>
481typename slist<T, Alloc>::reference
483{
484 return static_cast<node_t*>(head_.next)->value;
485}
486
487
488
489/** returns reference to first element in list.
490 *
491 * @c *this must not be empty. There's no check on wheter the first element exists.
492 * It's semantically equivalent to @c *this->begin()
493 *
494 * @b complexity: O(1)
495 */
496template <typename T, class Alloc>
497typename slist<T, Alloc>::const_reference
499{
500 return static_cast<node_t*>(head_.next)->value;
501}
502
503
504
505/** insert a copy of @a value at the front of the list so that the current list comes behind it.
506 *
507 * @param value to be inserted at front
508 *
509 * It's semantically equivalent to <tt>this->insert(this->begin(), value)</tt>.
510 * All iterators stay valid.
511 *
512 * @b complexity: O(1)
513 */
514template <typename T, class Alloc>
515void slist<T, Alloc>::push_front(const T& value)
516{
517 node_base_t* node = make_node(value);
518 node->next = head_.next;
519 head_.next = node;
520}
521
522
523
524/** erases the first element in the list.
525 *
526 * It's semantically equivalent to <tt>this->erase(this->begin())</tt>.
527 * All iterators except @c this->begin() stay valid.
528 *
529 * @b complexity: O(1)
530 */
531template <typename T, class Alloc>
533{
534 unlink_and_destroy_after(&head_);
535}
536
537
538
539/** inserts a new element before iterator @a position and returns iterator to it.
540 *
541 * @param position must be valid in @c *this and should not be @c this->before_begin()
542 * @param value to be inserted
543 *
544 * @warning this operation is in linear time because it has to call @c prior(position).
545 * Try to use @c insert_after whenever you can.
546 *
547 * All iterators stay valid.
548 *
549 * @b complexity: O(N) with N = <tt>std::distance(this->begin(), position)</tt>
550 */
551template <typename T, class Alloc>
552typename slist<T, Alloc>::iterator
553slist<T, Alloc>::insert(iterator position, const T& value)
554{
555 const iterator before_position = prior(position);
556 return insert_after(before_position, value);
557}
558
559
560
561/** inserts @a n copies of @a value before iterator @a position.
562 *
563 * @param position must be valid in @c *this and should not be @c this->before_begin()
564 * @param n number of copies to be inserted.
565 * @param value to be inserted
566 *
567 * @warning this operation is in linear time because it has to call @c prior(position).
568 * Try to use @c insert_after whenever you can.
569 *
570 * All iterators stay valid.
571 *
572 * @b complexity: O(N1) + O(N2) with N1 = <tt>std::distance(this->begin(), position)</tt>
573 * and N2 = @a n.
574 */
575template <typename T, class Alloc>
576void slist<T, Alloc>::insert(iterator position, size_type n, const T& value)
577{
578 const iterator before_position = prior(position);
579 insert_after(before_position, n, value);
580}
581
582
583
584/** inserts a copy of a range before iterator @a position.
585 *
586 * @param position must be valid in @c *this and should not be @c this->before_begin()
587 * @param first iterator to first element to be inserted.
588 * @param last iterator to position after last element to be insert. Must be forward reachable
589 * from @a first.
590 *
591 * @warning this operation is in linear time because it has to call @c prior(position).
592 * Try to use @c insert_after whenever you can.
593 *
594 * All iterators stay valid.
595 *
596 * @b complexity: O(N1) + O(N2) with N1 = <tt>std::distance(this->begin(), position)</tt>
597 * and N2 = @a <tt>std::distance(first, last)</tt>
598 */
599template <typename T, class Alloc>
600template <typename InputIterator>
601void slist<T, Alloc>::insert(iterator position, InputIterator first, InputIterator last)
602{
603 const iterator before_position = prior(position);
604 insert_after(before_position, first, last);
605}
606
607
608
609/** inserts a new element after iterator @a position and returns iterator to it.
610 *
611 * @param position must be valid in @c *this and should not be @c this->end()
612 * @param value to be inserted
613 *
614 * All iterators stay valid.
615 *
616 * @b complexity: O(1)
617 */
618template <typename T, class Alloc>
619typename slist<T, Alloc>::iterator
620slist<T, Alloc>::insert_after(iterator position, const T& value)
621{
622 node_base_t* new_node = make_node(value);
623 link_after(position.node_, new_node);
624 return iterator(new_node);
625}
626
627
628
629/** inserts @a n copies of @a value after iterator @a position.
630 *
631 * @param position must be valid in @c *this and should not be @c this->end()
632 * @param n number of copies to be inserted.
633 * @param value to be inserted
634 *
635 * All iterators stay valid.
636 *
637 * @b complexity: O(N) with N = @a n.
638 */
639template <typename T, class Alloc>
640void slist<T, Alloc>::insert_after(iterator position, size_type n, const value_type& value)
641{
642 node_base_t* node = position.node_;
643 for (size_type i = 0; i < n; ++i)
644 {
645 node_t* new_node = make_node(value);
646 link_after(node, new_node);
647 node = new_node;
648 }
649}
650
651
652
653/** inserts a copy of a range before iterator @a position.
654 *
655 * @param position must be valid in @c *this and should not be @c this->end()
656 * @param first iterator to first element to be inserted.
657 * @param last iterator to position after last element to be insert. Must be forward reachable
658 * from @a first.
659 *
660 * All iterators stay valid.
661 *
662 * @b complexity: O(N) with N = <tt>std::distance(first, last)</tt>.
663 */
664template <typename T, class Alloc>
665template <typename InputIterator>
666void slist<T, Alloc>::insert_after(iterator position, InputIterator first, InputIterator last)
667{
668 insert_after(position, first, last, meta::Wrap<typename meta::IsIntegral<InputIterator>::Type>());
669}
670
671
672
673/** removes element at iterator @a position from the list and return iterator to the next element.
674 *
675 * @param position element to be erased.
676 * Must be valid in @c *this and should not be @c this->before_begin() or @c this->end().
677 *
678 * @warning this operation is in linear time because it has to call @c prior(position).
679 * Try to use @c erase_after whenever you can.
680 *
681 * All iterators except @a position stay valid.
682 *
683 * @b complexity: O(N) with N = <tt>std::distance(this->begin(), position)</tt>
684 */
685template <typename T, class Alloc>
686typename slist<T, Alloc>::iterator
687slist<T, Alloc>::erase(iterator position)
688{
689 iterator before_position = prior(position);
690 erase_after(before_position);
691 return ++before_position;
692}
693
694
695
696/** removes element in range from the list and return iterator to the next element.
697 *
698 * @param position iterator to first element to be erased.
699 * Must be valid in @c *this and should not be @c this->before_begin() or @c this->end().
700 * @param last iterator to position behind last element to be erased, must be valid in
701 * @c *this and forward reachable from @a position.
702 *
703 * @warning this operation is in linear time because it has to call @c prior(position).
704 * Try to use @c erase_after whenever you can.
705 *
706 * All iterators except these in range [ @a position, @a last ) stay valid.
707 *
708 * @b complexity: O(N1) + O(N2) with N1 = <tt>std::distance(this->begin(), position)</tt> and
709 * N2 = <tt>std::distance(position, last)</tt>
710 */
711template <typename T, class Alloc>
712typename slist<T, Alloc>::iterator
713slist<T, Alloc>::erase(iterator position, iterator last)
714{
715 iterator before_position = prior(position);
716 erase_after(before_position, last);
717 return ++before_position;
718}
719
720
721
722/** removes element after iterator @a position from the list.
723 *
724 * @param position iterator to position before element to be erased, must be valid in @c *this,
725 * and should not be @c this->end()
726 *
727 * All iterators except the one after @a position stay valid.
728 *
729 * @b complexity: O(1)
730 */
731template <typename T, class Alloc>
732void slist<T, Alloc>::erase_after(iterator position)
733{
734 LASS_ASSERT(position.node_ && position.node_->next);
735 unlink_and_destroy_after(position.node_);
736}
737
738
739
740/** removes element in range from the list and return iterator to the next element.
741 *
742 * @param position iterator to position before first element to be erased.
743 * Must be valid in @c *this and should not be @c this->end()
744 * @param last iterator to position behind last element to be erased, must be valid in
745 * @c *this and forward reachable from @a position.
746 *
747 * All iterators except these in range ( @a position, @a last ) stay valid.
748 *
749 * @b complexity: O(N) with N = <tt>std::distance(position, last)</tt>
750 */
751template <typename T, class Alloc>
752void slist<T, Alloc>::erase_after(iterator position, iterator last)
753{
754 LASS_ASSERT(position.node_);
755 while (position.node_->next != last.node_)
756 {
757 erase_after(position);
758 }
759}
760
761
762
763/** exchange all data between two lists.
764 *
765 * All iterators stay valid.
766 *
767 * @b complexity: O(1)
768 */
769template <typename T, class Alloc>
771{
772 LASS_ASSERT(get_allocator() == other.get_allocator());
773 std::swap(head_.next, other.head_.next);
774}
775
776
777
778/** removes all elements from the list
779 *
780 * @b complexity: O(N) with N = @c this->size()
781 */
782template <typename T, class Alloc>
784{
786 swap(temp);
787}
788
789
790
791/** moves all elements from @a other to @c *this before @a position without copying, and
792 * clears @a other.
793 *
794 * @param position must be valid in @c *this and should not be @c this->before_begin()
795 * @param other must not be the same as @c *this (<tt>&other != this</tt>).
796 *
797 * @warning this operation is in linear time because it has to call @c prior(position).
798 * Try to use @c splice_after whenever you can.
799 *
800 * All iterators stay valid.
801 *
802 * @b complexity: O(N1) + O(N2) with N1 = <tt>std::distance(this->begin(), position)</tt>
803 * and N2 = @c other.size()
804 */
805template <typename T, class Alloc>
806void slist<T, Alloc>::splice(iterator position, slist<T, Alloc>& other)
807{
808 const iterator before_position = prior(position);
809 splice_after(before_position, other);
810}
811
812
813
814/** moves @a x from @a other to @c *this before @a position without copying.
815 *
816 * @param position must be valid in @c *this and should not be @c this->before_begin()
817 * @param other may be the same as @c *this.
818 * @param x must be valid in @c other and should not be @c other.before_begin()
819 *
820 * @warning this operation is in linear time because it has to call @c prior(position) and
821 * @c prior(x). Try to use @c splice_after whenever you can.
822 *
823 * All iterators stay valid.
824 *
825 * @b complexity: O(N1) + O(N2) with N1 = <tt>std::distance(this->begin(), position)</tt>
826 * and N2 = <tt>std::distance(other.begin(), x)</tt>
827 */
828template <typename T, class Alloc>
829void slist<T, Alloc>::splice(iterator position, slist<T, Alloc>& other, iterator x)
830{
831 const iterator before_position = prior(position);
832 const iterator before_x = other.prior(x);
833 splice_after(before_position, other, before_x);
834}
835
836
837
838/** moves [ @a first , @a last ) from @a other to @c *this before @a position without copying.
839 *
840 * @param position must be valid in @c *this and should not be @c this->before_begin().
841 * @a position should not be an element of [ @a first , @a last ).
842 * @param other may be the same as @c *this.
843 * @param first must be valid in @c other and should not be @c other.before_begin()
844 * @param last must be valid in @c other and should be forward reachable from @a first.
845 *
846 * @warning this operation is in linear time because it has to call @c prior(position) and
847 * @c prior(x). Try to use @c splice_after whenever you can.
848 *
849 * All iterators stay valid.
850 *
851 * @b complexity: O(N1) + O(N2) with N1 = <tt>std::distance(this->begin(), position)</tt>
852 * and N2 = <tt>std::distance(other.begin(), x)</tt>
853 */
854template <typename T, class Alloc>
855void slist<T, Alloc>::splice(iterator position, slist<T, Alloc>& other, iterator first, iterator last)
856{
857 const iterator before_position = prior(position);
858 const iterator before_first = other.prior(first);
859 const iterator before_last = other.prior(last, before_first);
860 splice_after(before_position, other, before_first, before_last);
861}
862
863
864
865/** moves all elements from @a other to @c *this after @a position without copying, and
866 * clears @a other.
867 *
868 * @param position must be valid in @c *this and should not be @c this->end()
869 * @param other must not be the same as @c *this (<tt>&other != this</tt>).
870 *
871 * All iterators stay valid.
872 *
873 * @b complexity: O(N) with N = @c other.size()
874 */
875template <typename T, class Alloc>
876void slist<T, Alloc>::splice_after(iterator position, slist<T, Alloc>& other)
877{
878 node_base_t* other_before_last = &other.head_;
879 while (other_before_last->next)
880 {
881 other_before_last = other_before_last->next;
882 }
883
884 splice_after(position.node_, &other.head_, other_before_last);
885}
886
887
888
889/** moves element before @a before_x from @a other to @c *this after @a position without copying.
890 *
891 * @param position must be valid in @c *this and should not be @c this->end()
892 * @param other may be the same as @c *this.
893 * @param before_x must be valid in @c other and should not be @c other.end()
894 *
895 * All iterators stay valid.
896 *
897 * @b complexity: O(1)</tt>
898 */
899template <typename T, class Alloc>
900void slist<T, Alloc>::splice_after(iterator position, slist<T, Alloc>& /*other*/, iterator before_x)
901{
902 splice_after(position.node_, before_x.node_, before_x.node_->next);
903}
904
905
906
907/** moves ( before_first, before_last ] from @a other to @c *this after @a position without copying.
908 *
909 * @param position must be valid in @c *this and should not be @c this->end().
910 * @a position should not be an element of ( before_first, before_last ].
911 * @param other may be the same as @c *this.
912 * @param before_first must be valid in @c other and should not be @c other.end()
913 * @param before_last must be valid in @c other and should be forward reachable from @a before_first.
914 *
915 * All iterators stay valid.
916 *
917 * @b complexity: O(1)
918 */
919template <typename T, class Alloc>
920void slist<T, Alloc>::splice_after(iterator position, slist<T, Alloc>& /*other*/, iterator before_first,
921 iterator before_last)
922{
923 splice_after(position.node_, before_first.node_, before_last.node_);
924}
925
926
927
928/** removes all elements with iterarors @c i for which <tt>*i == value</tt>
929 *
930 * @param value value of the elements that must be removed.
931 *
932 * @b complexity: O(N) with N = @c this->size()
933 */
934template <typename T, class Alloc>
935void slist<T, Alloc>::remove(const T& value)
936{
937 node_base_t* node = &head_;
938 while (node->next)
939 {
940 if (static_cast<node_t*>(node->next)->value == value)
941 {
942 unlink_and_destroy_after(node);
943 }
944 else
945 {
946 node = node->next;
947 }
948 }
949}
950
951
952
953/** removes all elements with iterarors @c i for which @c predicate(*i) yields @c true.
954 *
955 * @param predicate should returns true for the elements that must be removed.
956 *
957 * @b complexity: O(N) with N = @c this->size()
958 */
959template <typename T, class Alloc>
960template <class UnaryPredicate>
961void slist<T, Alloc>::remove_if(UnaryPredicate predicate)
962{
963 node_base_t* node = &head_;
964 while (node->next)
965 {
966 if (predicate(static_cast<node_t*>(node->next)->value))
967 {
968 unlink_and_destroy_after(node);
969 }
970 else
971 {
972 node = node->next;
973 }
974 }
975}
976
977
978
979/** removes all but the first element in every consecutive group of equal elements.
980 *
981 * The relative order of elements that are not removed is unchanged, and iterators to elements
982 * that are not removed remain valid.
983 *
984 * @b complexity: O(N) with N = @c this->size()
985 */
986template <typename T, class Alloc>
988{
989 node_base_t* node = head_.next;
990 if (!node)
991 {
992 return;
993 }
994 while (node->next)
995 {
996 if (static_cast<node_t*>(node)->value == static_cast<node_t*>(node->next)->value)
997 {
998 unlink_and_destroy_after(node);
999 }
1000 else
1001 {
1002 node = node->next;
1003 }
1004 }
1005}
1006
1007
1008
1009/** removes all but the first element in every consecutive group of equivalent elements by a predicate.
1010 *
1011 * @param predicate two elements @c *i and @c *j are considered equivalent if
1012 * <tt>predicate(*i, *j)</tt> is true.
1013 *
1014 * The relative order of elements that are not removed is unchanged, and iterators to elements
1015 * that are not removed remain valid.
1016 *
1017 * @b complexity: O(N) with N = @c this->size()
1018 */
1019template <typename T, class Alloc>
1020template <class BinaryPredicate>
1021void slist<T, Alloc>::unique(BinaryPredicate predicate)
1022{
1023 node_base_t* node = head_.next;
1024 if (!node)
1025 {
1026 return;
1027 }
1028 while (node->next)
1029 {
1030 if (predicate(static_cast<node_t*>(node)->value, static_cast<node_t*>(node->next)->value))
1031 {
1032 unlink_and_destroy_after(node);
1033 }
1034 else
1035 {
1036 node = node->next;
1037 }
1038 }
1039}
1040
1041
1042
1043/** Merge two sorted containers to one big sorted.
1044 *
1045 * Both @c *this and @a other must be sorted according to @c operator<, and they must be
1046 * distinct (<tt>&other != this</tt>). This function removes all of @a other's elements and
1047 * inserts them in order into @c *this. The merge is stable; that is, if an element from @c *this
1048 * is equivalent to one from @a other, then the element from @c *this will precede the one from
1049 * @a other. All iterators to elements in @c *this and @a other remain valid.
1050 *
1051 * @param other the other sorted @c slist
1052 *
1053 * @b complexity: O(N1) + O(N2) with N1 = @c this->size() and N2 = @c other.size()
1054 */
1055template <typename T, class Alloc>
1057{
1058 merge(other, std::less<value_type>());
1059}
1060
1061
1062
1063/** Merge two by @a compare sorted containers to one big sorted.
1064 *
1065 * Both @c *this and @a other must be sorted according to @a compare, and they must be
1066 * distinct (<tt>&other != this</tt>). This function removes all of @a other's elements and
1067 * inserts them in order into @c *this. The merge is stable; that is, if an element from @c *this
1068 * is equivalent to one from @a other, then the element from @c *this will precede the one from
1069 * @a other. All iterators to elements in @c *this and @a other remain valid.
1070 *
1071 * @param other the other sorted @c slist
1072 * @param compare must define strict weak ordening. Both containers must be sorted
1073 * by this predicate.
1074 *
1075 * @b complexity: O(N1) + O(N2) with N1 = @c this->size() and N2 = @c other.size()
1076 */
1077template <typename T, class Alloc>
1078template <class BinaryPredicate>
1079void slist<T, Alloc>::merge(slist<T, Alloc>& other, BinaryPredicate compare)
1080{
1081 node_base_t* node = &head_;
1082 while (node->next && other.head_.next)
1083 {
1084 if (compare(static_cast<node_t*>(other.head_.next)->value,
1085 static_cast<node_t*>(node->next)->value))
1086 {
1087 splice_after(node, &other.head_, other.head_.next);
1088 }
1089 node = node->next;
1090 }
1091 if (other.head_.next)
1092 {
1093 node->next = other.head_.next;
1094 other.head_.next = 0;
1095 }
1096}
1097
1098
1099
1100/** Sorts @c *this according to @c operator<.
1101 *
1102 * The sort is stable, that is, the relative order of equivalent elements is preserved.
1103 * All iterators remain valid and continue to point to the same elements.
1104 *
1105 * @b complexity: O(N log N) with N = @c this->size()
1106 */
1107template <typename T, class Alloc>
1109{
1110 sort(std::less<value_type>());
1111}
1112
1113
1114
1115
1116
1117
1118
1119/** Sorts @c *this according to @a compare.
1120 *
1121 * @param compare must define strict weak ordening. Both containers must be sorted
1122 * by this predicate.
1123 *
1124 * The sort is stable, that is, the relative order of equivalent elements is preserved.
1125 * All iterators remain valid and continue to point to the same elements.
1126 *
1127 * @b complexity: O(N log N) with N = @c this->size()
1128 */
1129template <typename T, class Alloc>
1130template <class BinaryPredicate>
1131void slist<T, Alloc>::sort(BinaryPredicate compare)
1132{
1133 if (head_.next && head_.next->next)
1134 {
1135 slist<T, Alloc> carry;
1136 slist<T, Alloc> counter[64];
1137 size_type fill = 0;
1138 while (!empty())
1139 {
1140 splice_after(&carry.head_, &head_, head_.next);
1141 size_type i = 0;
1142 while (i < fill && !counter[i].empty())
1143 {
1144 counter[i].merge(carry, compare);
1145 carry.swap(counter[i]);
1146 ++i;
1147 }
1148 carry.swap(counter[i]);
1149 if (i == fill)
1150 {
1151 ++fill;
1152 }
1153 }
1154 for (size_type i = 1; i < fill; ++i)
1155 {
1156 counter[i].merge(counter[i - 1], compare);
1157 }
1158 swap(counter[fill - 1]);
1159 }
1160}
1161
1162
1163
1164/** reverses the order of the elements.
1165 *
1166 * All iterators stay valid.
1167 *
1168 * @b complexity: O(N) with N = @c this->size()
1169 */
1170template <typename T, class Alloc>
1172{
1173 node_base_t* begin = 0;
1174 while (head_.next)
1175 {
1176 node_base_t* node = head_.next;
1177 head_.next = node->next;
1178 node->next = begin;
1179 begin = node;
1180 }
1181 head_.next = begin;
1182}
1183
1184// --- protected -----------------------------------------------------------------------------------
1185
1186
1187
1188// --- private -------------------------------------------------------------------------------------
1189
1190/** @internal
1191 */
1192template <typename T, class Alloc>
1193typename slist<T, Alloc>::node_t*
1194slist<T, Alloc>::make_node(const T& value) const
1195{
1196 allocator_type allocator = get_allocator();
1197 node_allocator_type node_allocator = node_allocator_type(allocator);
1198
1199 node_t* node = node_allocator.allocate(1);
1200 try
1201 {
1202 std::allocator_traits<allocator_type>::construct(allocator, &node->value, value);
1203 }
1204 catch (...)
1205 {
1206 node_allocator.deallocate(node, 1);
1207 throw;
1208 }
1209 node->next = 0;
1210 return node;
1211}
1212
1213
1214
1215/** @internal
1216 */
1217template <typename T, class Alloc>
1218void slist<T, Alloc>::unlink_and_destroy_after(node_base_t* before) const
1219{
1220 allocator_type allocator = get_allocator();
1221 node_allocator_type node_allocator = node_allocator_type(allocator);
1222
1223 LASS_ASSERT(before && before->next);
1224
1225 node_base_t* node = before->next;
1226 before->next = node->next;
1227 std::allocator_traits<allocator_type>::destroy(allocator, &static_cast<node_t*>(node)->value);
1228 node_allocator.deallocate(static_cast<node_t*>(node), 1);
1229}
1230
1231
1232
1233/** @internal
1234 */
1235template <typename T, class Alloc>
1236void slist<T, Alloc>::link_after(node_base_t* position, node_base_t* node) const
1237{
1238 LASS_ASSERT(position && node);
1239 node->next = position->next;
1240 position->next = node;
1241}
1242
1243
1244
1245/** @internal
1246 */
1247template <typename T, class Alloc>
1248void slist<T, Alloc>::splice_after(node_base_t* position, node_base_t* before_first,
1249 node_base_t* before_last) const
1250{
1251 LASS_ASSERT(before_first != before_last);
1252 if (position != before_first && position != before_last)
1253 {
1254 node_base_t* const first = before_first->next;
1255 before_first->next = before_last->next;
1256 before_last->next = position->next;
1257 position->next = first;
1258 }
1259}
1260
1261
1262
1263/** @internal
1264 */
1265template <typename T, class Alloc>
1266template <typename IntegerType>
1267void slist<T, Alloc>::insert_after(iterator position, IntegerType n, IntegerType value, meta::Wrap<meta::True>)
1268{
1269 insert_after(position, static_cast<size_t>(n), static_cast<value_type>(value));
1270}
1271
1272
1273
1274/** @internal
1275 */
1276template <typename T, class Alloc>
1277template <typename InputIterator>
1278void slist<T, Alloc>::insert_after(iterator position, InputIterator first, InputIterator last, meta::Wrap<meta::False>)
1279{
1280 while (first != last)
1281 {
1282 node_t* new_node = make_node(*first);
1283 link_after(position.node_, new_node);
1284 ++position;
1285 ++first;
1286 }
1287}
1288
1289
1290
1291// --- free functions ------------------------------------------------------------------------------
1292
1293/** returns wether @a a and @a b are lexicographical idential.
1294 * @relates slist
1295 *
1296 * @param a first @c slist
1297 * @param b second @c slist
1298 *
1299 * returns true if <tt>a.size() == b.size()</tt> and each element of @a is considered
1300 * equal to its corresponding element in @a b by using @c operator==
1301 *
1302 * @complexity O(N) with N = <tt>a.size() == b.size() ? a.size() : 1</tt>
1303 */
1304template <typename T, class Alloc>
1306{
1307 typedef typename slist<T, Alloc>::const_iterator const_iterator;
1308 const const_iterator a_end = a.end();
1309 const const_iterator b_end = b.end();
1310 const_iterator i = a.begin();
1311 const_iterator j = b.begin();
1312 while (i != a_end && j != b_end)
1313 {
1314 if (*i != *j)
1315 {
1316 return false;
1317 }
1318 ++i;
1319 ++j;
1320 }
1321 return i == a_end && j == b_end;
1322}
1323
1324
1325
1326/** returns wether @a a and @a b are not lexicographical idential.
1327 * @relates slist
1328 *
1329 * @param a first @c slist
1330 * @param b second @c slist
1331 *
1332 * Is equivalent to <tt>!(a == b)</tt>
1333 *
1334 * @complexity O(N) with N = <tt>a.size() == b.size() ? a.size() : 1</tt>
1335 */
1336template <typename T, class Alloc>
1338{
1339 return !(a == b);
1340}
1341
1342
1343
1344/** returns wether @a a is lexicographical less than @a b.
1345 * @relates slist
1346 *
1347 * @param a first @c slist
1348 * @param b second @c slist
1349 *
1350 * returns true if for the first difference between @a a and @a b the element of @a a is less
1351 * than the corresponding one of @a b. In case no different elements between @a and @a b can be
1352 * found, it returns true if <tt>a.size() < b.size()</tt>
1353 *
1354 * @complexity O(N) with N = <tt>std::min(a.size(), b.size())</tt>
1355 */
1356template <typename T, class Alloc>
1358{
1359 typedef typename slist<T, Alloc>::const_iterator const_iterator;
1360 const const_iterator a_end = a.end();
1361 const const_iterator b_end = b.end();
1362 const_iterator i = a.begin();
1363 const_iterator j = b.begin();
1364 while (i != a_end && j != b_end)
1365 {
1366 if (!(*i < *j))
1367 {
1368 return false;
1369 }
1370 ++i;
1371 ++j;
1372 }
1373 return j != b_end;
1374}
1375
1376
1377
1378/** returns wether @a b is lexicographical less than @a a.
1379 * @relates slist
1380 *
1381 * @param a first @c slist
1382 * @param b second @c slist
1383 *
1384 * Is equivalent to <tt>(b < a)</tt>
1385 *
1386 * @complexity O(N) with N = <tt>std::min(a.size(), b.size())</tt>
1387 */
1388template <typename T, class Alloc>
1390{
1391 return b < a;
1392}
1393
1394
1395
1396/** returns wether @a a is lexicographical less or equal to @a b.
1397 * @relates slist
1398 *
1399 * @param a first @c slist
1400 * @param b second @c slist
1401 *
1402 * Is equivalent to <tt>!(b < a)</tt>
1403 *
1404 * @complexity O(N) with N = <tt>std::min(a.size(), b.size())</tt>
1405 */
1406template <typename T, class Alloc>
1408{
1409 return !(b < a);
1410}
1411
1412
1413
1414/** returns wether @a b is lexicographical less or equal to @a a.
1415 * @relates slist
1416 *
1417 * @param a first @c slist
1418 * @param b second @c slist
1419 *
1420 * Is equivalent to <tt>!(a < b)</tt>
1421 *
1422 * @complexity O(N) with N = <tt>std::min(a.size(), b.size())</tt>
1423 */
1424template <typename T, class Alloc>
1426{
1427 return !(a < b);
1428}
1429
1430
1431
1432/** @relates slist
1433 * writes list to output stream.
1434 *
1435 * @param ostream should be a good stream.
1436 * @param container @c slist to be written as [foo, bar, spam, ham]
1437 *
1438 * @b complexity: O(N) with N = @c container.size()
1439 */
1440template <typename T, class Alloc, typename Char, typename Traits>
1441std::basic_ostream<Char, Traits>&
1442operator<<(std::basic_ostream<Char, Traits>& ostream,
1443 const slist<T, Alloc>& container)
1444{
1445 return impl::print_sequence(
1446 ostream, container.begin(), container.end(), "[", ", ", "]");
1447}
1448
1449
1450
1451/** @relates slist
1452 * reads list from stream.
1453 *
1454 * @param istream should be a good stream.
1455 * @param container @c slist to be read as [foo, bar, spam, ham]
1456 *
1457 * @b complexity: O(N) with N = number of elements to be read.
1458 */
1459template <typename T, class Alloc, typename Char, typename Traits>
1460std::basic_istream<Char, Traits>&
1461operator>>(std::basic_istream<Char, Traits>& istream,
1462 slist<T, Alloc>& container)
1463{
1464 std::basic_istream<Char, Traits>& result =
1465 impl::read_container<impl::slist_traits, impl::value_traits, T, Char>(
1466 istream, container, '[', ',', 0, ']');
1467 container.reverse();
1468 return result;
1469}
1470
1471
1472
1473}
1474
1475}
1476
1477// EOF
void clear()
removes all elements from the list
Definition slist.inl:783
void sort()
Sorts *this according to operator<.
Definition slist.inl:1108
void splice_after(iterator position, slist< T, Alloc > &other)
moves all elements from other to *this after position without copying, and clears other.
Definition slist.inl:876
void merge(slist< T, Alloc > &other)
Merge two sorted containers to one big sorted.
Definition slist.inl:1056
bool operator==(const slist< T, Alloc > &a, const slist< T, Alloc > &b)
returns wether a and b are lexicographical idential.
Definition slist.inl:1305
slist(const Alloc &allocator=Alloc())
Creates an empty list, using the provided allocator.
Definition slist.inl:82
iterator end()
returns an iterator for the position after the last element of the list.
Definition slist.inl:255
iterator before_begin()
returns an iterator for the position before the first element of the list.
Definition slist.inl:285
~slist()
destroys all elements and frees memory.
Definition slist.inl:150
reference front()
returns reference to first element in list.
Definition slist.inl:482
iterator begin()
returns an iterator to the first element of the list.
Definition slist.inl:229
void push_front(const T &value)
insert a copy of value at the front of the list so that the current list comes behind it.
Definition slist.inl:515
void unique()
removes all but the first element in every consecutive group of equal elements.
Definition slist.inl:987
bool operator>=(const slist< T, Alloc > &a, const slist< T, Alloc > &b)
Definition slist.inl:1425
size_type size() const
returns the N, the number of elements in the list.
Definition slist.inl:411
iterator erase(iterator position)
removes element at iterator position from the list and return iterator to the next element.
Definition slist.inl:687
size_type max_size() const
returns a very rough estimation on what's the maximum number of elements you can ever have in an slis...
Definition slist.inl:432
bool operator<(const slist< T, Alloc > &a, const slist< T, Alloc > &b)
returns wether a is lexicographical less than b.
Definition slist.inl:1357
bool empty() const
returns wether the list is empty.
Definition slist.inl:398
iterator insert(iterator position, const T &value)
inserts a new element before iterator position and returns iterator to it.
Definition slist.inl:553
void remove(const T &value)
removes all elements with iterarors i for which *i == value
Definition slist.inl:935
void splice(iterator position, slist< T, Alloc > &other)
moves all elements from other to *this before position without copying, and clears other.
Definition slist.inl:806
bool operator!=(const slist< T, Alloc > &a, const slist< T, Alloc > &b)
returns wether a and b are not lexicographical idential.
Definition slist.inl:1337
slist< T, Alloc > & operator=(slist< T, Alloc > other)
replace *this by a copy of other.
Definition slist.inl:167
iterator prior(iterator position) const
return the iterator that sits position and start searching for it from start.
Definition slist.inl:318
void pop_front()
erases the first element in the list.
Definition slist.inl:532
iterator insert_after(iterator position, const T &value)
inserts a new element after iterator position and returns iterator to it.
Definition slist.inl:620
void resize(size_type n, const T &value=T())
at the end of the list, inserts copies of value or erases elements so that list size is n.
Definition slist.inl:450
void erase_after(iterator position)
removes element after iterator position from the list.
Definition slist.inl:732
void swap(slist< T, Alloc > &other)
void remove_if(UnaryPredicate predicate)
removes all elements with iterarors i for which predicate(*i) yields true.
Definition slist.inl:961
std::basic_istream< Char, Traits > & operator>>(std::basic_istream< Char, Traits > &istream, slist< T, Alloc > &container)
reads list from stream.
Definition slist.inl:1461
allocator_type get_allocator() const
returns the memory model of the list.
Definition slist.inl:216
void reverse()
reverses the order of the elements.
Definition slist.inl:1171
bool operator>(const slist< T, Alloc > &a, const slist< T, Alloc > &b)
returns wether b is lexicographical less than a.
Definition slist.inl:1389
bool operator<=(const slist< T, Alloc > &a, const slist< T, Alloc > &b)
returns wether a is lexicographical less or equal to b.
Definition slist.inl:1407
lass extensions to the standard library
Library for Assembled Shared Sources.
Definition config.h:53