aGrUM 3.1.1
a C++ library for (probabilistic) graphical models
list_tpl.h
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2026 by *
5 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
6 * - Christophe GONZALES(_at_AMU) *
7 * *
8 * The aGrUM/pyAgrum library is free software; you can redistribute it *
9 * and/or modify it under the terms of either : *
10 * *
11 * - the GNU Lesser General Public License as published by *
12 * the Free Software Foundation, either version 3 of the License, *
13 * or (at your option) any later version, *
14 * - the MIT license (MIT), *
15 * - or both in dual license, as here. *
16 * *
17 * (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18 * *
19 * This aGrUM/pyAgrum library is distributed in the hope that it will be *
20 * useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26 * OTHER DEALINGS IN THE SOFTWARE. *
27 * *
28 * See LICENCES for more details. *
29 * *
30 * SPDX-FileCopyrightText: Copyright 2005-2026 *
31 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
32 * - Christophe GONZALES(_at_AMU) *
33 * SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34 * *
35 * Contact : info_at_agrum_dot_org *
36 * homepage : http://agrum.gitlab.io *
37 * gitlab : https://gitlab.com/agrumery/agrum *
38 * *
39 ****************************************************************************/
40
41#pragma once
42
43
50
51// to ease parser
53
54namespace gum {
55
56 // ===========================================================================
57 // ===========================================================================
58 // === BUCKET IMPLEMENTATION ===
59 // ===========================================================================
60 // ===========================================================================
61
62 // default constructor
63 template < typename Val >
65 // for debugging purposes
66 GUM_CONSTRUCTOR(ListBucket);
67 }
68
69 // constructor for Val rvalues
70 template < typename Val >
71 ListBucket< Val >::ListBucket(Val&& v) noexcept : _val_{std::move(v)} {
72 // for debugging purposes
73 GUM_CONSTRUCTOR(ListBucket);
74 }
75
76 // emplace constructor
77 template < typename Val >
78 template < typename... Args >
80 _val_(std::forward< Args >(args)...) {
81 // for debugging purposes
82 GUM_CONSTRUCTOR(ListBucket);
83 }
84
85 // copy constructor
86 template < typename Val >
88 // for debugging purposes
89 GUM_CONS_CPY(ListBucket);
90 }
91
92 // copy operator
93 template < typename Val >
95 // for debugging purposes
96 GUM_OP_CPY(ListBucket);
97
98 // no need to avoid self assignment
99 _val_ = src._val_;
100 return *this;
101 }
102
103 // WARNING: during its deletion, the bucket does not take care of properly
104 // re-chaining the chained list. This should be done by the Lists themselves
105 template < typename Val >
107 // for debugging purposes
108 GUM_DESTRUCTOR(ListBucket);
109 }
110
111 // equality check
112 template < typename Val >
114 return (src._val_ == _val_);
115 }
116
117 // inequality check
118 template < typename Val >
120 return (src._val_ != _val_);
121 }
122
123 // dereferencing operator
124 template < typename Val >
125 const Val& ListBucket< Val >::operator*() const noexcept {
126 return _val_;
127 }
128
129 // dereferencing operator
130 template < typename Val >
132 return _val_;
133 }
134
135 // returns the bucket toward the next element
136 template < typename Val >
138 return _next_;
139 }
140
141 // returns the bucket toward the preceding element
142 template < typename Val >
144 return _prev_;
145 }
146
147 // ===========================================================================
148 // ===========================================================================
149 // === UNSAFE_CONST_LIST_ITERATOR IMPLEMENTATION ===
150 // ===========================================================================
151 // ===========================================================================
152
153 // default constructor
154 template < typename Val >
156 // for debugging purposes
157 GUM_CONSTRUCTOR(ListConstIterator);
158 }
159
160 // default constructor
161 template < typename Val >
163 _bucket_{theList._deb_list_} {
164 // for debugging purposes
165 GUM_CONSTRUCTOR(ListConstIterator);
166 }
167
168 // copy constructor
169 template < typename Val >
171 _bucket_{src._bucket_} {
172 // for debugging purposes
173 GUM_CONS_CPY(ListConstIterator);
174 }
175
176 // move constructor
177 template < typename Val >
179 _bucket_{std::move(src._bucket_)} {
180 // for debugging purposes
181 GUM_CONS_MOV(ListConstIterator);
182 }
183
184 // Constructor for an iterator pointing to the \e ind_eltth element of a
185 // List.
186 template < typename Val >
188 // for debugging purposes
189 GUM_CONSTRUCTOR(ListConstIterator);
190
191 // check if the index ind_elt passed as parameter is valid
192 if (ind_elt >= theList._nb_elements_) {
193 GUM_ERROR(UndefinedIteratorValue, "Not enough elements in the list")
194 }
195
196 // check if it is faster to find the indexth element from the start or
197 // from the end of the list
198 if (ind_elt < (theList._nb_elements_ >> 1)) {
199 // find the element we shall point to src the start of the list
200 for (_bucket_ = theList._deb_list_; ind_elt; --ind_elt, _bucket_ = _bucket_->_next_) {}
201 } else {
202 // find the element we shall point to src the end of the list
203 for (_bucket_ = theList._end_list_, ind_elt = theList._nb_elements_ - ind_elt - 1; ind_elt;
204 --ind_elt, _bucket_ = _bucket_->_prev_) {}
205 }
207
208 // Destructor
209 template < typename Val >
211 // for debugging purposes
212 GUM_DESTRUCTOR(ListConstIterator);
213 }
214
215 // Copy operator
216 template < typename Val >
219 // for debugging purposes
220 GUM_OP_CPY(ListConstIterator);
221
222 _bucket_ = src._bucket_;
223 return *this;
224 }
225
226 // move operator
227 template < typename Val >
230 // for debugging purposes
231 GUM_OP_MOV(ListConstIterator);
232 _bucket_ = src._bucket_;
233 return *this;
234 }
235
236 // returns the bucket the iterator is pointing to
237 template < typename Val >
241
242 // Makes the iterator point toward nothing
243 template < typename Val >
245 _bucket_ = nullptr;
246 }
247
248 // positions the iterator to the end of the list
249 template < typename Val >
251 _bucket_ = nullptr;
252 }
253
254 // returns a bool indicating whether the iterator points to the end of the
255 // list
256 template < typename Val >
257 bool ListConstIterator< Val >::isEnd() const noexcept {
258 return (_bucket_ == nullptr);
259 }
260
261 // makes the iterator point to the next element in the List
262 template < typename Val >
264 // if we are pointing to an element of the chained list, just
265 // point on the next bucket in this list
266 if (_bucket_ != nullptr) { _bucket_ = _bucket_->_next_; }
267
268 return *this;
269 }
270
271 // makes the iterator point to the next element in the List
272 template < typename Val >
274 typename ListConstIterator< Val >::difference_type i) noexcept {
275 if (i >= 0) {
276 for (; i && (_bucket_ != nullptr); --i, _bucket_ = _bucket_->_next_) {}
277 } else {
278 for (; i && (_bucket_ != nullptr); ++i, _bucket_ = _bucket_->_prev_) {}
279 }
280 return *this;
281 }
282
283 // makes the iterator point to the preceding element in the List
284 template < typename Val >
286 // if we are pointing to an element of the chained list, just
287 // point on the preceding bucket in this list
288 if (_bucket_ != nullptr) { _bucket_ = _bucket_->_prev_; }
289
290 return *this;
291 }
292
293 // makes the iterator point to i elements before in the list
294 template < typename Val >
296 typename ListConstIterator< Val >::difference_type i) noexcept {
297 if (i >= 0) {
298 for (; i && (_bucket_ != nullptr); --i, _bucket_ = _bucket_->_prev_) {}
299 } else {
300 for (; i && (_bucket_ != nullptr); ++i, _bucket_ = _bucket_->_next_) {}
301 }
302 return *this;
303 }
304
305 // returns a new iterator
306 template < typename Val >
311
312 // returns a new iterator
313 template < typename Val >
318
319 // checks whether two iterators point toward different elements
320 template < typename Val >
322 return (_bucket_ != src._bucket_);
323 }
324
325 // checks whether two iterators point toward the same elements.
326 template < typename Val >
328 return (_bucket_ == src._bucket_);
329 }
330
331 // dereferences the value pointed to by the iterator
332 template < typename Val >
334 if (_bucket_ != nullptr) return &(_bucket_->_val_);
335 else { GUM_ERROR(UndefinedIteratorValue, "Accessing a NULL object") }
336 }
337
338 // gives access to the content of the iterator
339 template < typename Val >
341 if (_bucket_ != nullptr) return _bucket_->_val_;
342 else { GUM_ERROR(UndefinedIteratorValue, "Accessing a NULL object") }
343 }
344
345 // for STL compliance, a distance operator
346 template < typename Val >
350
351 for (ListConstIterator< Val > iter3 = iter2; iter1 != iter3; ++iter3, ++res) {}
352
353 return res;
354 }
355
356 // ===========================================================================
357 // ===========================================================================
358 // === UNSAFE_LIST_ITERATOR IMPLEMENTATION ===
359 // ===========================================================================
360 // ===========================================================================
361
362 // basic constructor
363 template < typename Val >
365 GUM_CONSTRUCTOR(ListIterator);
366 }
367
368 // constructor for a begin
369 template < typename Val >
371 ListConstIterator< Val >(theList) {
372 GUM_CONSTRUCTOR(ListIterator);
373 }
374
375 // copy constructor
376 template < typename Val >
379 GUM_CONS_CPY(ListIterator);
380 }
381
382 // move constructor
383 template < typename Val >
385 ListConstIterator< Val >(std::move(src)) {
386 GUM_CONS_MOV(ListIterator);
387 }
388
389 // Constructor for an iterator pointing to the \e ind_eltth element of a
390 // List.
391 template < typename Val >
393 ListConstIterator< Val >(theList, ind_elt) {
394 GUM_CONSTRUCTOR(ListIterator);
395 }
396
397 // Copy operator
398 template < typename Val >
400 GUM_OP_CPY(ListIterator);
402 return *this;
403 }
404
405 // move operator
406 template < typename Val >
408 GUM_OP_MOV(ListIterator);
410 return *this;
411 }
412
413 // Destructor
414 template < typename Val >
416 GUM_DESTRUCTOR(ListIterator);
417 }
418
419 // test equality
420 template < typename Val >
421 bool ListIterator< Val >::operator==(const ListIterator< Val >& src) const noexcept {
423 }
424
425 // test inequality
426 template < typename Val >
427 bool ListIterator< Val >::operator!=(const ListIterator< Val >& src) const noexcept {
428 return !operator==(src);
429 }
430
431 // makes the iterator point to the next element in the List
432 template < typename Val >
437
438 // makes the iterator point to i elements further in the List
439 template < typename Val >
445
446 // makes the iterator point to the preceding element in the List
447 template < typename Val >
452
453 // makes the iterator point to i elements before in the List
454 template < typename Val >
460
461 // returns a new iterator
462 template < typename Val >
467
468 // returns a new iterator
469 template < typename Val >
474
475 // dereferences the value pointed to by the iterator
476 template < typename Val >
478 return const_cast< Val* >(ListConstIterator< Val >::operator->());
479 }
481 // dereferences the value pointed to by the iterator
482 template < typename Val >
486
487 // gives access to the content of the iterator
488 template < typename Val >
490 return const_cast< Val& >(ListConstIterator< Val >::operator*());
491 }
492
493 // gives access to the content of the iterator
494 template < typename Val >
498
499 // ===========================================================================
500 // ===========================================================================
501 // === SAFE LIST CONST ITERATOR IMPLEMENTATION ===
502 // ===========================================================================
503 // ===========================================================================
504
505 // basic constructor
506 template < typename Val >
508 // for debugging purposes
509 GUM_CONSTRUCTOR(ListConstIteratorSafe);
510 }
511
512 // Constructor for a begin
513 template < typename Val >
515 _list_{&theList}, _bucket_{theList._deb_list_} {
516 // for debugging purposes
517 GUM_CONSTRUCTOR(ListConstIteratorSafe);
518
519 // add the iterator to the list of safe iterators
520 theList._safe_iterators_.push_back(this);
521 }
522
523 // copy constructor
524 template < typename Val >
528 // for debugging purposes
529 GUM_CONS_CPY(ListConstIteratorSafe);
530
531 // add the iterator to the list of safe iterators
532 if (_list_ != nullptr) _list_->_safe_iterators_.push_back(this);
533 }
535 // Constructor for an iterator pointing to the \e ind_eltth element of a
536 // List.
537 template < typename Val >
538
540 _list_{&theList} {
541 // for debugging purposes
542 GUM_CONSTRUCTOR(ListConstIteratorSafe);
543
544 // check if the index ind_elt passed as parameter is valid
545 if (ind_elt >= _list_->_nb_elements_) {
546 GUM_ERROR(UndefinedIteratorValue, "Not enough elements in the list")
548
549 // check if it is faster to find the indexth element src the start or
550 // src the end of the list
551 if (ind_elt < (_list_->_nb_elements_ >> 1)) {
552 // find the element we shall point to src the start of the list
553 for (_bucket_ = _list_->_deb_list_; ind_elt; --ind_elt, _bucket_ = _bucket_->_next_) {}
554 } else {
555 // find the element we shall point to src the end of the list
556 for (_bucket_ = _list_->_end_list_, ind_elt = _list_->_nb_elements_ - ind_elt - 1; ind_elt;
557 --ind_elt, _bucket_ = _bucket_->_prev_) {}
558 }
559
560 // add the iterator to the list of safe iterators
561 theList._safe_iterators_.push_back(this);
562 }
563
564 // move constructor
565 template < typename Val >
569 // for debugging purposes
570 GUM_CONS_MOV(ListConstIteratorSafe);
571
572 if (_list_ != nullptr) {
573 // substitute src by this in the list of safe iterators
574 std::vector< ListConstIteratorSafe< Val >* >& vect = _list_->_safe_iterators_;
576 for (auto ptr = vect.rbegin(); ptr != vect.rend(); --ptr) {
577 if (*ptr == &src) {
578 *ptr = this;
579 break;
580 }
581 }
582
583 src._list_ = nullptr;
584 src._bucket_ = nullptr;
585 src._null_pointing_ = false;
586 }
587 }
588
589 // remove the iterator for its list' safe iterators list
590 template < typename Val >
592 // find where the iterator is
593 std::vector< ListConstIteratorSafe< Val >* >& vect = _list_->_safe_iterators_;
594
595 for (auto i = vect.size() - 1; i >= 0; --i) {
596 if (vect[i] == this) {
597 vect.erase(vect.begin() + i);
598 break;
599 }
600 }
601 }
602
603 // Copy operator
604 template < typename Val >
607 // avoid self assignment
608 if (this != &src) {
609 // for debugging purposes
610 GUM_OP_CPY(ListConstIteratorSafe);
611
612 // check if src and this belong to the same list. If this is not
613 // the case, we shall remove this from its iterator's list and
614 // put it into src's list one.
615 if (_list_ && (src._list_ != _list_)) {
616 _removeFromSafeList_();
617 _list_ = nullptr;
618 }
619
620 // if necessary, put this into the same list of safe iterators as src
621 if (src._list_ && (src._list_ != _list_)) {
622 try {
623 src._list_->_safe_iterators_.push_back(this);
624 } catch (...) {
625 _list_ = nullptr;
626 _bucket_ = nullptr;
627 _null_pointing_ = false;
628 throw;
629 }
630 }
631
632 _list_ = src._list_;
633 _bucket_ = src._bucket_;
634 _prev_current_bucket_ = src._prev_current_bucket_;
635 _next_current_bucket_ = src._next_current_bucket_;
636 _null_pointing_ = src._null_pointing_;
637 }
638
639 return *this;
640 }
641
642 // move operator
643 template < typename Val >
646 // avoid self assignment
647 if (this != &src) {
648 // for debugging purposes
649 GUM_OP_MOV(ListConstIteratorSafe);
650
651 // if the two iterators do not point to the same list, remove
652 // the current iterator from its safe iterators list
653 if ((_list_ != nullptr) && (src._list_ != _list_)) {
654 _removeFromSafeList_();
655 _list_ = nullptr;
656 }
657
658 // now if src points to a list, put this at its location
659 if ((src._list_ != nullptr)) {
660 std::vector< ListConstIteratorSafe< Val >* >& vect = src._list_->_safe_iterators_;
661 Idx index_src = Size(vect.size()) - 1;
662
663 for (;; --index_src) {
664 if (vect[index_src] == &src) { break; }
665 }
666
667 if (_list_ == nullptr) {
668 vect[index_src] = this;
669 } else {
670 vect.erase(vect.begin() + index_src);
671 }
672 }
673
674 _list_ = src._list_;
675 _bucket_ = src._bucket_;
676 _prev_current_bucket_ = src._prev_current_bucket_;
677 _next_current_bucket_ = src._next_current_bucket_;
678 _null_pointing_ = src._null_pointing_;
679
680 src._list_ = nullptr;
681 src._bucket_ = nullptr;
682 src._null_pointing_ = false;
683 }
684
685 return *this;
686 }
687
688 // Destructor
689 template < typename Val >
691 // for debugging purposes
692 GUM_DESTRUCTOR(ListConstIteratorSafe);
693
694 // remove the iterator src the table's iterator list
696 }
697
698 // returns the bucket the iterator is pointing to
699 template < typename Val >
701 return _bucket_;
702 }
703
704 // Makes the iterator point toward nothing
705 template < typename Val >
707 // remove the iterator src the list's iterator list
709
710 // set its list as well as the element it points to to nullptr
711 _list_ = nullptr;
712 _bucket_ = nullptr;
713 _null_pointing_ = false;
714 }
715
716 // positions the iterator to the end of the list
717 template < typename Val >
721
722 // returns a bool indicating whether the iterator points to the end of the
723 // list
724 template < typename Val >
726 return _null_pointing_
727 ? (_next_current_bucket_ == nullptr) && (_prev_current_bucket_ == nullptr)
728 : (_bucket_ == nullptr);
729 }
730
731 // makes the iterator point to the next element in the List
732 template < typename Val >
734 // check if we are pointing to something that has been deleted
735 if (_null_pointing_) {
736 _null_pointing_ = false;
737
738 // if we are pointing to an element of the chained list that has been
739 // deleted
740 // but that has a next element, just point on the latter
741 if (_next_current_bucket_ != nullptr) {
743 return *this;
744 }
745
746 // here we were pointing on an extremity of the list (either end or rend)
747 // if prev_current_bucket is not null, then we are at rend and doing
748 // a ++ shall now point to the beginning of the list
749 if (_prev_current_bucket_ != nullptr) {
751 return *this;
752 }
753
754 // here, we are at the end of the chained list, hence we shall remain at
755 // end
756 _bucket_ = nullptr;
757 return *this;
758 } else {
759 // if we are pointing to an element of the chained list, just
760 // point on the next bucket in this list
761 if (_bucket_ != nullptr) { _bucket_ = _bucket_->_next_; }
762
763 return *this;
764 }
765 }
766
767 // makes the iterator point to i elements before in the List
768 template < typename Val >
770 // check if we are pointing to something that has been deleted
771 if (_null_pointing_) {
772 _null_pointing_ = false;
773
774 // if we are pointing to an element of the chained list that has been
775 // deleted
776 // but that has a preceding element, just point on the latter
777 if (_prev_current_bucket_ != nullptr) {
778 _bucket_ = _prev_current_bucket_->_prev_;
779 } else {
780 // here we were pointing on an extremity of the list (either end or
781 // rend)
782 // if next_current_bucket is not null, then we are at end and doing
783 // a -- shall now point to the beginning of the list
784 if (_next_current_bucket_ != nullptr) {
785 _bucket_ = _next_current_bucket_;
786 } else {
787 // here, we are at the rend of the chained list, hence we shall remain
788 // at rend
789 _bucket_ = nullptr;
790 return *this;
791 }
792 }
793 } else {
794 // if we are pointing to an element of the chained list, just
795 // point on the preceding bucket in this list
796 if (_bucket_ != nullptr) { _bucket_ = _bucket_->_prev_; }
797 }
798
799 for (--i; i && (_bucket_ != nullptr); --i, _bucket_ = _bucket_->_prev_) {}
800
801 return *this;
802 }
804 // makes the iterator point to the next element in the List
805 template < typename Val >
807 // check if we are pointing to something that has been deleted
808 if (_null_pointing_) {
809 _null_pointing_ = false;
810
811 // if we are pointing to an element of the chained list that has been
812 // deleted
813 // but that has a next element, just point on the latter
814 if (_next_current_bucket_ != nullptr) {
816 } else {
817 // here we were pointing on an extremity of the list (either end or
818 // rend)
819 // if prev_current_bucket is not null, then we are at rend and doing
820 // a ++ shall now point to the beginning of the list
821 if (_prev_current_bucket_ != nullptr) {
823 } else {
824 // here, we are at the end of the chained list, hence we shall
825 // remain at end
826 _bucket_ = nullptr;
827 return *this;
829 }
830 } else {
831 // if we are pointing to an element of the chained list, just
832 // point on the next bucket in this list
833 if (_bucket_ != nullptr) { _bucket_ = _bucket_->_next_; }
834 }
835
836 for (--i; i && (_bucket_ != nullptr); --i, _bucket_ = _bucket_->_next_) {}
837
838 return *this;
839 }
840
841 // makes the iterator point to the next element in the List
842 template < typename Val >
845 if (!i) return *this;
846
847 if (i < 0) return _opMinus_(-i);
848 else return _opPlus_(i);
849 }
850
851 // makes the iterator point to the preceding element in the List
852 template < typename Val >
854 // check if we are pointing to something that has been deleted
855 if (_null_pointing_) {
856 _null_pointing_ = false;
857
858 // if we are pointing to an element of the chained list that has been
859 // deleted
860 // but that has a preceding element, just point on the latter
861 if (_prev_current_bucket_ != nullptr) {
863 return *this;
864 }
865
866 // here we were pointing on an extremity of the list (either end or rend)
867 // if next_current_bucket is not null, then we are at end and doing
868 // a -- shall now point to the beginning of the list
869 if (_next_current_bucket_ != nullptr) {
871 return *this;
872 }
873
874 // here, we are at the rend of the chained list, hence we shall remain
875 // at rend
876 _bucket_ = nullptr;
877 return *this;
878 } else {
879 // if we are pointing to an element of the chained list, just
880 // point on the preceding bucket in this list
881 if (_bucket_ != nullptr) { _bucket_ = _bucket_->_prev_; }
882
883 return *this;
884 }
885 }
886
887 // makes the iterator point to i elements before in the List
888 template < typename Val >
891 if (!i) return *this;
892
893 if (i < 0) return _opPlus_(-i);
894 else return _opMinus_(i);
895 }
896
897 // returns a new iterator
898 template < typename Val >
903
904 // returns a new iterator
905 template < typename Val >
910
911 // checks whether two iterators point toward different elements
912 template < typename Val >
918
919 // checks whether two iterators point toward the same elements.
920 template < typename Val >
926
927 // dereferences the value pointed to by the iterator
928 template < typename Val >
930 if (_bucket_ != nullptr) return &(_bucket_->_val_);
931 else { GUM_ERROR(UndefinedIteratorValue, "Accessing a NULL object") }
932 }
933
934 // gives access to the content of the iterator
935 template < typename Val >
937 if (_bucket_ != nullptr) return _bucket_->_val_;
938 else { GUM_ERROR(UndefinedIteratorValue, "Accessing a NULL object") }
939 }
940
941 // for STL compliance, a distance operator
942 template < typename Val >
945 const ListConstIteratorSafe< Val >& iter2) {
947 ListConstIteratorSafe< Val > iter3{iter2};
948
949 for (; iter1 != iter3; ++iter3, ++res) {}
950
951 return res;
952 }
953
954 // ===========================================================================
955 // ===========================================================================
956 // === LIST ITERATOR IMPLEMENTATION ===
957 // ===========================================================================
958 // ===========================================================================
959
960 // basic constructor
961 template < typename Val >
963 GUM_CONSTRUCTOR(ListIteratorSafe);
964 }
965
966 // constructor for a begin
967 template < typename Val >
968
970 ListConstIteratorSafe< Val >(theList) {
971 GUM_CONSTRUCTOR(ListIteratorSafe);
972 }
973
974 // copy constructor
975 template < typename Val >
978 GUM_CONS_CPY(ListIteratorSafe);
979 }
980
981 // Constructor for an iterator pointing to the \e ind_eltth element of a
982 // List.
983 template < typename Val >
985 ListConstIteratorSafe< Val >(theList, ind_elt) {
986 GUM_CONSTRUCTOR(ListIteratorSafe);
987 }
988
989 // move constructor
990 template < typename Val >
995
996 // Copy operator
997 template < typename Val >
999 // for debugging purposes
1000 GUM_OP_CPY(ListIteratorSafe);
1002 return *this;
1003 }
1004
1005 // move operator
1006 template < typename Val >
1008 // for debugging purposes
1009 GUM_OP_MOV(ListIteratorSafe);
1011 return *this;
1013
1014 // Destructor
1015 template < typename Val >
1019
1020 // test equality
1021 template < typename Val >
1025
1026 // test inequality
1027 template < typename Val >
1029 return !operator==(src);
1030 }
1031
1032 // makes the iterator point to the next element in the List
1033 template < typename Val >
1038
1039 // makes the iterator point to the next element in the List
1040 template < typename Val >
1046
1047 // makes the iterator point to the preceding element in the List
1048 template < typename Val >
1053
1054 // makes the iterator point to the preceding element in the List
1055 template < typename Val >
1057 typename ListIteratorSafe< Val >::difference_type i) noexcept {
1059 return *this;
1060 }
1061
1062 // returns a new iterator
1063 template < typename Val >
1065 typename ListIteratorSafe< Val >::difference_type i) noexcept {
1066 return ListIteratorSafe< Val >(*this) += i;
1067 }
1068
1069 // returns a new iterator
1070 template < typename Val >
1072 typename ListIteratorSafe< Val >::difference_type i) noexcept {
1073 return ListIteratorSafe< Val >(*this) -= i;
1074 }
1075
1076 // dereferences the value pointed to by the iterator
1077 template < typename Val >
1079 return const_cast< Val* >(ListConstIteratorSafe< Val >::operator->());
1080 }
1081
1082 // dereferences the value pointed to by the iterator
1083 template < typename Val >
1087
1088 // gives access to the content of the iterator
1089 template < typename Val >
1091 return const_cast< Val& >(ListConstIteratorSafe< Val >::operator*());
1092 }
1093
1094 // gives access to the content of the iterator
1095 template < typename Val >
1099
1100 // ===========================================================================
1101 // ===========================================================================
1102 // === LIST IMPLEMENTATION ===
1103 // ===========================================================================
1104 // ===========================================================================
1105
1106 // a function used to perform copies of elements of Lists
1107 template < typename Val >
1110 ListBucket< Val >* old_ptr = nullptr;
1111 ListBucket< Val >* new_elt = nullptr;
1112
1113 // copy src's list
1114 try {
1115 for (ptr = src._deb_list_; ptr != nullptr; ptr = ptr->_next_) {
1116 // create a copy bucket
1117 new_elt = new ListBucket< Val >(*ptr);
1118
1119 // rechain properly the new list (the next field is already initialized
1120 // with nullptr)
1121 new_elt->_prev_ = old_ptr;
1122
1123 if (old_ptr) old_ptr->_next_ = new_elt;
1124 else _deb_list_ = new_elt;
1125
1126 old_ptr = new_elt;
1127 }
1128 } catch (...) {
1129 // problem: we could not allocate an element in the list => we delete
1130 // the elements created so far and we throw an exception
1131 for (; _deb_list_ != nullptr; _deb_list_ = const_cast< ListBucket< Val >* >(ptr)) {
1132 ptr = _deb_list_->_next_;
1133 delete _deb_list_;
1134 }
1135
1136 _deb_list_ = nullptr;
1137 throw;
1138 }
1139
1140 // update properly the end of the chained list and the number of elements
1141 _end_list_ = old_ptr;
1142 _nb_elements_ = src._nb_elements_;
1143 }
1144
1145 // deletes all the elements of a chained list.
1146 template < typename Val >
1148 // first we update all the safe iterators of the list : they should now
1149 // point to end/rend
1150 for (const auto ptr_iter: _safe_iterators_) {
1151 ptr_iter->clear();
1152 }
1153
1154 // clear all the values
1155 for (ListBucket< Val >*ptr = _deb_list_, *next_ptr = nullptr; ptr != nullptr; ptr = next_ptr) {
1156 next_ptr = ptr->_next_;
1157 delete ptr;
1158 }
1159
1160 _nb_elements_ = 0;
1161 _deb_list_ = nullptr;
1162 _end_list_ = nullptr;
1164
1165 // A basic constructor that creates an empty list
1166 template < typename Val >
1168 // for debugging purposes
1169 GUM_CONSTRUCTOR(List);
1170
1171 // reserve space for only the default number of iterators
1173 }
1174
1175 // Copy constructor
1176 template < typename Val >
1178 // for debugging purposes
1179 GUM_CONS_CPY(List);
1180
1181 // copy the elements
1182 _copy_elements_(src);
1183
1184 // reserve space for only the default number of iterators
1186 }
1187
1188 // move constructor
1189 template < typename Val >
1191 _deb_list_{std::move(src._deb_list_)}, _end_list_{std::move(src._end_list_)},
1192 _nb_elements_{std::move(src._nb_elements_)},
1193 _safe_iterators_{std::move(src._safe_iterators_)} {
1194 // for debugging purposes
1195 GUM_CONS_MOV(List);
1196
1197 src._deb_list_ = nullptr;
1198 src._end_list_ = nullptr;
1199 src._nb_elements_ = 0;
1200 src._safe_iterators_.clear();
1201 }
1202
1203 // initializer_list constructor
1204 template < typename Val >
1205 List< Val >::List(std::initializer_list< Val > list) {
1206 // for debugging purposes
1207 GUM_CONSTRUCTOR(List);
1208
1209 // adding all the elements
1210 for (const auto& val: list) {
1211 pushBack(val);
1212 }
1213
1214 // reserve space for only the default number of iterators
1215 _safe_iterators_.reserve(GUM_DEFAULT_ITERATOR_NUMBER);
1216 }
1217
1218 // Destructor
1219 template < typename Val >
1221 // for debugging (although this program is bug-free)
1222 GUM_DESTRUCTOR(List);
1223
1224 // we detach all the safe iterators attached to the current List and we
1225 // remove all the elements from the list
1226 clear();
1227 }
1228
1229 // Copy operator. The List iterator's list is not shared with that of \e src.
1230 template < typename Val >
1232 // avoid self assignment
1233 if (this != &src) {
1234 // for debugging purposes
1235 GUM_OP_CPY(List);
1236
1237 // remove the old content of 'this' and update accordingly the iterators
1238 clear();
1239
1240 // perform the copy
1241 _copy_elements_(src);
1242 }
1243
1244 return *this;
1245 }
1246
1247 // move operator
1248 template < typename Val >
1250 // avoid self assignment
1251 if (this != &src) {
1252 // for debugging purposes
1253 GUM_OP_MOV(List);
1254
1255 // remove the old content of 'this' and update accordingly the iterators
1256 clear();
1257
1258 // perform the move
1259 _deb_list_ = std::move(src._deb_list_);
1260 _end_list_ = std::move(src._end_list_);
1261 _nb_elements_ = std::move(src._nb_elements_);
1262 _safe_iterators_ = std::move(src._safe_iterators_);
1263
1264 src._deb_list_ = nullptr;
1265 src._end_list_ = nullptr;
1266 src._nb_elements_ = 0;
1267 src._safe_iterators_.clear();
1268 }
1269
1270 return *this;
1271 }
1273 // the iterator pointing to the end of the List
1274 template < typename Val >
1276 return *(reinterpret_cast< const ListConstIteratorSafe< Val >* >(_list_end_safe_));
1277 }
1278
1279 // the iterator pointing to the end of the List
1280 template < typename Val >
1282 return *(reinterpret_cast< const ListIteratorSafe< Val >* >(_list_end_safe_));
1284
1285 // the iterator pointing to the end of the List
1286 template < typename Val >
1288 return *(reinterpret_cast< const ListConstIterator< Val >* >(_list_end_));
1289 }
1290
1291 // the iterator pointing to the end of the List
1292 template < typename Val >
1294 return *(reinterpret_cast< const ListIterator< Val >* >(_list_end_));
1295 }
1296
1297 // the iterator pointing to the end of the List
1298 template < typename Val >
1300 return *(reinterpret_cast< const ListConstIterator< Val >* >(_list_end_));
1301 }
1302
1303 // the iterator pointing to the rend (just before the beginning) of the List
1304 template < typename Val >
1306 return *(reinterpret_cast< const ListConstIteratorSafe< Val >* >(_list_end_safe_));
1307 }
1308
1309 // the iterator pointing to the rend (just before the beginning) of the List
1310 template < typename Val >
1312 return *(reinterpret_cast< const ListIteratorSafe< Val >* >(_list_end_safe_));
1313 }
1314
1315 // the iterator pointing to the rend (just before the beginning) of the List
1316 template < typename Val >
1318 return *(reinterpret_cast< const ListConstIterator< Val >* >(_list_end_));
1319 }
1320
1321 // the iterator pointing to the rend (just before the beginning) of the List
1322 template < typename Val >
1324 return *(reinterpret_cast< const ListIterator< Val >* >(_list_end_));
1325 }
1326
1327 // the iterator pointing to the rend (just before the beginning) of the List
1328 template < typename Val >
1330 return *(reinterpret_cast< const ListConstIterator< Val >* >(_list_end_));
1331 }
1332
1333 // the iterator pointing to the beginning of the List
1334 template < typename Val >
1338
1339 // the iterator pointing to the beginning of the List
1340 template < typename Val >
1342 return ListIteratorSafe< Val >{*this};
1343 }
1344
1345 // the iterator pointing to the beginning of the List
1346 template < typename Val >
1349 }
1350
1351 // the iterator pointing to the beginning of the List
1352 template < typename Val >
1357 // the iterator pointing to the beginning of the List
1358 template < typename Val >
1362
1363 // the iterator pointing to the rbegin (the last element) of the List
1364 template < typename Val >
1369
1370 // the iterator pointing to the rbegin (the last element) of the List
1371 template < typename Val >
1373 if (_nb_elements_) return ListIteratorSafe< Val >{*this, _nb_elements_ - 1};
1375 }
1376
1377 // the iterator pointing to the rbegin (the last element) of the List
1378 template < typename Val >
1383
1384 // the iterator pointing to the rbegin (the last element) of the List
1385 template < typename Val >
1390
1391 // the iterator pointing to the rbegin (the last element) of the List
1392 template < typename Val >
1397
1398 // create a new bucket with a given value
1399 template < typename Val >
1401 return new ListBucket< Val >(val);
1402 }
1403
1404 // create a new bucket with a given value
1405 template < typename Val >
1407 return new ListBucket< Val >(std::move(val));
1408 }
1409
1410 // create an emplace bucket
1411 template < typename Val >
1412 template < typename... Args >
1415 std::forward< Args >(args)...);
1416 }
1417
1418 // insert a bucket at the front of the list
1419 template < typename Val >
1421 new_elt->_next_ = _deb_list_;
1422
1423 if (_deb_list_ != nullptr) _deb_list_->_prev_ = new_elt;
1424 else _end_list_ = new_elt;
1425
1426 _deb_list_ = new_elt;
1427
1428 // update the number of elements
1429 ++_nb_elements_;
1430
1431 // return the inserted element
1432 return new_elt->_val_;
1433 }
1434
1435 // insert a bucket at the end of the list
1436 template < typename Val >
1438 // place the bucket at the end of the list
1439 new_elt->_prev_ = _end_list_;
1440
1441 if (_end_list_ != nullptr) _end_list_->_next_ = new_elt;
1442 else _deb_list_ = new_elt;
1443
1444 _end_list_ = new_elt;
1445
1446 // update the number of elements
1447 ++_nb_elements_;
1448
1449 // returns the current value
1450 return new_elt->_val_;
1451 }
1452
1453 // Insertion of a new element (a copy) at the beginning of the chained list.
1454 template < typename Val >
1455 Val& List< Val >::pushFront(const Val& val) {
1456 return _pushFront_(_createBucket_(val));
1457 }
1458
1459 // Insertion of a new element (a copy) at the beginning of the chained list.
1460 template < typename Val >
1461 Val& List< Val >::pushFront(Val&& val) {
1462 return _pushFront_(_createBucket_(std::move(val)));
1463 }
1464
1465 // an alias for pushFront used for STL compliance
1466 template < typename Val >
1467 template < typename... Args >
1468 Val& List< Val >::push_front(Args&&... args) {
1469 return pushFront(std::forward< Args >(args)...);
1470 }
1471
1472 // emplace elements at the beginning of the chained list
1473 template < typename Val >
1474 template < typename... Args >
1475 Val& List< Val >::emplaceFront(Args&&... args) {
1476 return _pushFront_(_createEmplaceBucket_(std::forward< Args >(args)...));
1477 }
1478
1479 // Insertion of a new element (a copy) at the end of the chained list.
1480 template < typename Val >
1481 Val& List< Val >::pushBack(const Val& val) {
1482 return _pushBack_(_createBucket_(val));
1483 }
1484
1485 // pushBack for rvalues
1486 template < typename Val >
1487 Val& List< Val >::pushBack(Val&& val) {
1488 return _pushBack_(_createBucket_(std::move(val)));
1489 }
1490
1491 // an alias for pushBack used for STL compliance
1492 template < typename Val >
1493 template < typename... Args >
1494 Val& List< Val >::push_back(Args&&... args) {
1495 return pushBack(std::forward< Args >(args)...);
1496 }
1497
1498 // emplace elements at the end of the chained list
1499 template < typename Val >
1500 template < typename... Args >
1501 Val& List< Val >::emplaceBack(Args&&... args) {
1502 return _pushBack_(_createEmplaceBucket_(std::forward< Args >(args)...));
1503 }
1504
1505 // Insertion of a new element at the end of the chained list (alias of
1506 // pushBack)
1507 template < typename Val >
1508 Val& List< Val >::insert(const Val& val) {
1509 return pushBack(val);
1510 }
1511
1512 // insert for rvalues
1513 template < typename Val >
1514 Val& List< Val >::insert(Val&& val) {
1515 return pushBack(std::move(val));
1516 }
1517
1518 // returns the bucket corresponding to the ith position
1519 template < typename Val >
1521 ListBucket< Val >* ptr;
1522
1523 if (i < _nb_elements_ / 2) {
1524 for (ptr = _deb_list_; i; --i, ptr = ptr->_next_) {}
1525 } else {
1526 for (ptr = _end_list_, i = _nb_elements_ - i - 1; i; --i, ptr = ptr->_prev_) {}
1527 }
1528
1529 return ptr;
1530 }
1531
1532 // insert a new bucket before another one
1533 template < typename Val >
1535 new_elt->_next_ = current_elt;
1536 new_elt->_prev_ = current_elt->_prev_;
1537 current_elt->_prev_ = new_elt;
1538
1539 if (new_elt->_prev_ == nullptr) _deb_list_ = new_elt;
1540 else new_elt->_prev_->_next_ = new_elt;
1541
1542 // update the number of elements
1543 ++_nb_elements_;
1544
1545 // returns the current value
1546 return new_elt->_val_;
1547 }
1548
1549 // insert a new bucket after another one
1550 template < typename Val >
1552 new_elt->_prev_ = current_elt;
1553 new_elt->_next_ = current_elt->_next_;
1554 current_elt->_next_ = new_elt;
1555
1556 if (new_elt->_next_ == nullptr) _end_list_ = new_elt;
1557 else new_elt->_next_->_prev_ = new_elt;
1558
1559 // update the number of elements
1560 ++_nb_elements_;
1561
1562 // returns the current value
1563 return new_elt->_val_;
1564 }
1565
1566 // inserts a new element at the ith pos of the chained list
1567 template < typename Val >
1568 Val& List< Val >::insert(Size pos, const Val& val) {
1569 // if ther are fewer elements than pos, put the value at the end of the list
1570 if (_nb_elements_ <= pos) { return pushBack(val); }
1571
1572 return _insertBefore_(_createBucket_(val), _getIthBucket_(pos));
1573 }
1574
1575 // insert an rvalue at the ith pos of the chained list
1576 template < typename Val >
1577 Val& List< Val >::insert(Size pos, Val&& val) {
1578 // if ther are fewer elements than pos, put the value at the end of the list
1579 if (_nb_elements_ <= pos) { return pushBack(std::move(val)); }
1580
1581 return _insertBefore_(_createBucket_(std::move(val)), _getIthBucket_(pos));
1582 }
1583
1584 // inserts a new bucket before or after the location pointed to by an
1585 // iterator
1586 template < typename Val >
1588 ListBucket< Val >* new_elt,
1589 location place) {
1590 // find the location around which the new element should be inserted
1591 ListBucket< Val >* ptr;
1592
1593 if (iter._null_pointing_) {
1594 if (place == location::BEFORE) {
1595 ptr = iter._next_current_bucket_;
1596 } else {
1597 ptr = iter._prev_current_bucket_;
1598 }
1599 } else {
1600 ptr = iter._getBucket_();
1601 }
1602
1603 if (ptr == nullptr) {
1604 // here, we are at the end of the list
1605 return _pushBack_(new_elt);
1606 } else {
1607 switch (place) {
1608 case location::BEFORE : return _insertBefore_(new_elt, ptr);
1609
1610 case location::AFTER : return _insertAfter_(new_elt, ptr);
1611
1612 default : GUM_ERROR(FatalError, "List insertion for this location unimplemented")
1613 }
1614 }
1615 }
1616
1617 // inserts a new bucket before or after the location pointed to by an
1618 // iterator
1619 template < typename Val >
1621 ListBucket< Val >* new_elt,
1622 location place) {
1623 // find the location around which the new element should be inserted
1624 ListBucket< Val >* ptr = iter._getBucket_();
1625
1626 if (ptr == nullptr) {
1627 // here, we are at the end of the list
1628 return _pushBack_(new_elt);
1629 } else {
1630 switch (place) {
1631 case location::BEFORE : return _insertBefore_(new_elt, ptr);
1632
1633 case location::AFTER : return _insertAfter_(new_elt, ptr);
1634
1635 default : GUM_ERROR(FatalError, "List insertion for this location unimplemented")
1636 }
1637 }
1638 }
1639
1640 // inserts a new element before or after the location pointed to by an
1641 // iterator
1642 template < typename Val >
1643 Val& List< Val >::insert(const const_iterator_safe& iter, const Val& val, location place) {
1644 // if the iterator does not point to the list, raise an exception
1645 if (iter._list_ != this) {
1646 GUM_ERROR(InvalidArgument, "the iterator does not point to the correct list")
1647 }
1648
1649 return _insert_(iter, _createBucket_(val), place);
1650 }
1651
1652 // inserts a new element before or after the location pointed to by an
1653 // iterator
1654 template < typename Val >
1655 Val& List< Val >::insert(const const_iterator_safe& iter, Val&& val, location place) {
1656 // if the iterator does not point to the list, raise an exception
1657 if (iter._list_ != this) {
1658 GUM_ERROR(InvalidArgument, "the iterator does not point to the correct list")
1659 }
1660
1661 return _insert_(iter, _createBucket_(std::move(val)), place);
1662 }
1663
1664 // inserts a new element before or after the location pointed to by an
1665 // iterator
1666 template < typename Val >
1667 Val& List< Val >::insert(const const_iterator& iter, const Val& val, location place) {
1668 return _insert_(iter, _createBucket_(val), place);
1669 }
1670
1671 // inserts a new element before or after the location pointed to by an
1672 // iterator
1673 template < typename Val >
1674 Val& List< Val >::insert(const const_iterator& iter, Val&& val, location place) {
1675 return _insert_(iter, _createBucket_(std::move(val)), place);
1676 }
1677
1678 // emplace a new element before a given iterator
1679 template < typename Val >
1680 template < typename... Args >
1681 Val& List< Val >::emplace(const const_iterator& iter, Args&&... args) {
1682 return _insert_(iter, _createEmplaceBucket_(std::forward< Args >(args)...), location::BEFORE);
1683 }
1684
1685 // emplace a new element before a given iterator
1686 template < typename Val >
1687 template < typename... Args >
1688 Val& List< Val >::emplace(const const_iterator_safe& iter, Args&&... args) {
1689 return _insert_(iter, _createEmplaceBucket_(std::forward< Args >(args)...), location::BEFORE);
1690 }
1691
1692 // returns a reference to first element of a list
1693 template < typename Val >
1694 Val& List< Val >::front() const {
1695 if (_nb_elements_ == Size(0)) { GUM_ERROR(NotFound, "not enough elements in the chained list") }
1696
1697 return _deb_list_->_val_;
1698 }
1699
1700 // returns a reference to last element of a list
1701 template < typename Val >
1702 Val& List< Val >::back() const {
1703 if (_nb_elements_ == Size(0)) { GUM_ERROR(NotFound, "not enough elements in the chained list") }
1704
1705 return _end_list_->_val_;
1706 }
1707
1708 // returns the number of elements in the list.
1709 template < typename Val >
1710 Size List< Val >::size() const noexcept {
1711 return _nb_elements_;
1712 }
1713
1714 // checks whether there exists a given element in the list.
1715 template < typename Val >
1716 bool List< Val >::exists(const Val& val) const {
1717 for (ListBucket< Val >* ptr = _deb_list_; ptr != nullptr; ptr = ptr->_next_)
1718 if (ptr->_val_ == val) return true;
1719
1720 return false;
1721 }
1722
1723 // suppresses a given bucket from a chained list.
1724 template < typename Val >
1726 // perform deletion only if there is a bucket to remove
1727 if (bucket != nullptr) {
1728 // update the iterators pointing on this element
1729 for (const auto ptr_iter: _safe_iterators_) {
1730 if (ptr_iter->_bucket_ == bucket) {
1731 ptr_iter->_next_current_bucket_ = bucket->_prev_;
1732 ptr_iter->_prev_current_bucket_ = bucket->_next_;
1733 ptr_iter->_bucket_ = nullptr;
1734 ptr_iter->_null_pointing_ = true;
1735 } else {
1736 if (ptr_iter->_null_pointing_) {
1737 if (ptr_iter->_next_current_bucket_ == bucket)
1738 ptr_iter->_next_current_bucket_ = bucket->_prev_;
1739
1740 if (ptr_iter->_prev_current_bucket_ == bucket)
1741 ptr_iter->_prev_current_bucket_ = bucket->_next_;
1742 }
1743 }
1744 }
1745
1746 // set properly the begin and end of the chained list (the other chainings
1747 // will be performed by operator delete)
1748 if (bucket->_prev_ == nullptr) _deb_list_ = bucket->_next_;
1749 else bucket->_prev_->_next_ = bucket->_next_;
1750
1751 if (bucket->_next_ == nullptr) _end_list_ = bucket->_prev_;
1752 else bucket->_next_->_prev_ = bucket->_prev_;
1753
1754 // remove the current element src the list
1755 delete bucket;
1756
1757 --_nb_elements_;
1758 }
1759 }
1760
1761 // erases the ith element of the List (the first one is in position 0)
1762 template < typename Val >
1764 if (i >= _nb_elements_) return;
1765
1766 // erase the ith bucket
1768 }
1769
1770 // erases the element of the List pointed to by the iterator
1771 template < typename Val >
1773 _erase_(iter._getBucket_());
1774 }
1775
1776 // erases the element of the List pointed to by the iterator
1777 template < typename Val >
1779 _erase_(iter._getBucket_());
1780 }
1781
1782 // returns the bucket corresponding to a given value.
1783 template < typename Val >
1784 ListBucket< Val >* List< Val >::_getBucket_(const Val& val) const noexcept {
1785 for (ListBucket< Val >* ptr = _deb_list_; ptr != nullptr; ptr = ptr->_next_)
1786 if (ptr->_val_ == val) return ptr;
1787
1788 return nullptr;
1789 }
1790
1791 // erases the first element encountered with a given value
1792 template < typename Val >
1793 void List< Val >::eraseByVal(const Val& val) {
1794 _erase_(_getBucket_(val));
1795 }
1796
1797 // erases all the elements encountered with a given value
1798 template < typename Val >
1799 void List< Val >::eraseAllVal(const Val& val) {
1800 for (ListBucket< Val >*iter = _deb_list_, *next_bucket = nullptr; iter != nullptr;
1801 iter = next_bucket) {
1802 next_bucket = iter->_next_;
1803
1804 if (val == iter->_val_) _erase_(iter);
1805 }
1806 }
1807
1808 // removes the last element of a List
1809 template < typename Val >
1813
1814 // removes the first element of a List
1815 template < typename Val >
1819
1820 // returns a boolean indicating whether the chained list is empty
1821 template < typename Val >
1822 bool List< Val >::empty() const noexcept {
1823 return (_nb_elements_ == Size(0));
1824 }
1825
1826 // displays the content of a chained list
1827 template < typename Val >
1828 std::string List< Val >::toString() const {
1829 bool deja = false;
1830 std::stringstream stream;
1831 stream << "[";
1832
1833 for (ListBucket< Val >* ptr = _deb_list_; ptr != nullptr; ptr = ptr->_next_, deja = true) {
1834 if (deja) stream << " --> ";
1835
1836 stream << ptr->_val_;
1837 }
1838
1839 stream << "]";
1840
1841 return stream.str();
1842 }
1843
1844 // creates a list of mountains src a list of val
1845 template < typename Val >
1846 template < typename Mount >
1847 List< Mount > List< Val >::map(Mount (*f)(Val)) const {
1848 // create a new empty list
1849 List< Mount > list;
1850
1851 // fill the new list
1852 for (const_iterator iter = begin(); iter != end(); ++iter) {
1853 list.pushBack(f(*iter));
1854 }
1855
1856 return list;
1857 }
1858
1859 // creates a list of mountains src a list of val
1860 template < typename Val >
1861 template < typename Mount >
1862 List< Mount > List< Val >::map(Mount (*f)(Val&)) const {
1863 // create a new empty list
1864 List< Mount > list;
1865
1866 // fill the new list
1867 for (const_iterator iter = begin(); iter != end(); ++iter) {
1868 list.pushBack(f(*iter));
1869 }
1870
1871 return list;
1872 }
1873
1874 // creates a list of mountains src a list of val
1875 template < typename Val >
1876 template < typename Mount >
1877 List< Mount > List< Val >::map(Mount (*f)(const Val&)) const {
1878 // create a new empty list
1879 List< Mount > list;
1880
1881 // fill the new list
1882 for (const_iterator iter = begin(); iter != end(); ++iter) {
1883 list.pushBack(f(*iter));
1884 }
1885
1886 return list;
1887 }
1888
1889 // creates a list of mountains with a given value src a list of val
1890 template < typename Val >
1891 template < typename Mount >
1892 List< Mount > List< Val >::map(const Mount& mount) const {
1893 // create a new empty list
1894 List< Mount > list;
1895
1896 // fill the new list
1897 for (Size i = Size(0); i < _nb_elements_; ++i)
1898 list.pushBack(mount);
1899
1900 return list;
1901 }
1902
1903 // creates and insert a new element at the end of the list (alias of
1904 // pushBack).
1905 template < typename Val >
1906 Val& List< Val >::operator+=(const Val& val) {
1907 return pushBack(val);
1908 }
1909
1910 // creates and insert a new element at the end of the list (alias of
1911 // pushBack).
1912 template < typename Val >
1913 Val& List< Val >::operator+=(Val&& val) {
1914 return pushBack(std::move(val));
1915 }
1916
1917 // checks whether two lists are identical (same elements in the same order)
1918 template < typename Val >
1919 bool List< Val >::operator==(const List< Val >& src) const {
1920 // check if the two lists have at least the same number of elements
1921 if (_nb_elements_ != src._nb_elements_) return false;
1922
1923 // parse the two lists
1924 for (ListBucket< Val >*iter1 = _deb_list_, *iter2 = src._deb_list_; iter1 != nullptr;
1925 iter1 = iter1->_next_, iter2 = iter2->_next_)
1926 if (*iter1 != *iter2) return false;
1927
1928 return true;
1929 }
1930
1931 // checks whether two lists are different (different elements or orders)
1932 template < typename Val >
1933 bool List< Val >::operator!=(const List< Val >& src) const {
1934 return !operator==(src);
1935 }
1936
1937 // returns the ith element in the current chained list.
1938 template < typename Val >
1940 // check if we can return the element we ask for
1941 if (i >= _nb_elements_) { GUM_ERROR(NotFound, "not enough elements in the chained list") }
1942
1943 return **_getIthBucket_(i);
1944 }
1945
1946 // returns the ith element in the current chained list.
1947 template < typename Val >
1948 const Val& List< Val >::operator[](const Size i) const {
1949 // check if we can return the element we ask for
1950 if (i >= _nb_elements_) { GUM_ERROR(NotFound, "not enough elements in the chained list") }
1951
1952 return **_getIthBucket_(i);
1953 }
1954
1955 // replace the current list with another one
1956 template < typename Val >
1957 void List< Val >::swap(List& other_list) {
1958 std::swap(_deb_list_, other_list._deb_list_);
1959 std::swap(_end_list_, other_list._end_list_);
1960 std::swap(_nb_elements_, other_list._nb_elements_);
1961 std::swap(_safe_iterators_, other_list._safe_iterators_);
1962 }
1963
1964 // A \c << operator for List
1965 template < typename Val >
1966 std::ostream& operator<<(std::ostream& stream, const List< Val >& list) {
1967 stream << list.toString();
1968 return stream;
1969 }
1970
1971} /* namespace gum */
Exception : fatal (unknown ?) error.
Exception: at least one argument passed to a function is not what was expected.
Bucket for a chained list.
Definition list.h:113
Val _val_
Val is the value contained in the box.
Definition list.h:256
Val & operator*() noexcept
Dereferencing operator.
Definition list_tpl.h:131
const ListBucket< Val > * next() const noexcept
Returns the bucket toward the next element.
Definition list_tpl.h:137
ListBucket< Val > * _next_
Chaining toward the adjacent elements.
Definition list.h:252
const ListBucket< Val > * previous() const noexcept
Returns the bucket toward the preceding element.
Definition list_tpl.h:143
ListBucket< Val > & operator=(const ListBucket< Val > &src)
Copy operator.
Definition list_tpl.h:94
ListBucket()=delete
Removes empty constructor.
ListBucket(typename ListBucket< gum::Instantiation * >::Emplace, Args &&... args)
Definition list_tpl.h:79
bool operator!=(const ListBucket< Val > &src) const
Inequality check.
Definition list_tpl.h:119
Emplace
C dummy type for the emplace constructor.
Definition list.h:120
bool operator==(const ListBucket< Val > &src) const
Equality check.
Definition list_tpl.h:113
~ListBucket()
Class destructor.
Definition list_tpl.h:106
ListBucket< Val > * _prev_
Chaining toward the adjacent elements.
Definition list.h:251
Safe const iterators for Lists.
Definition list.h:2005
ListConstIteratorSafe< Val > & operator-=(difference_type i) noexcept
Makes the iterator point to i elements befor in the List.
Definition list_tpl.h:889
ListBucket< Val > * _bucket_
The bucket in the chained list pointed to by the iterator.
Definition list.h:2232
std::ptrdiff_t difference_type
Types for STL compliance.
Definition list.h:2015
ListConstIteratorSafe< Val > & _opMinus_(Size i) noexcept
Makes the iterator point to i elements before in the List.
Definition list_tpl.h:769
void _removeFromSafeList_() const
Remove the iterator for its list' safe iterators list.
Definition list_tpl.h:591
ListConstIteratorSafe() noexcept
Default constructor.
Definition list_tpl.h:507
ListConstIteratorSafe< Val > & _opPlus_(Size i) noexcept
Makes the iterator point to the next element in the List.
Definition list_tpl.h:806
ListConstIteratorSafe< Val > & operator++() noexcept
Makes the iterator point to the next element in the List.
Definition list_tpl.h:733
ListBucket< Val > * _getBucket_() const noexcept
Returns the bucket the iterator is pointing to.
Definition list_tpl.h:700
friend class List< Val >
class List must be a friend because it uses the getBucket method to speed up some processes.
Definition list.h:2224
ListConstIteratorSafe< Val > & operator=(const ListConstIteratorSafe< Val > &src)
Copy operator.
Definition list_tpl.h:606
void setToEnd()
Positions the iterator to the end of the list.
Definition list_tpl.h:718
const Val & operator*() const
Gives access to the content of the iterator.
Definition list_tpl.h:936
ListBucket< Val > * _next_current_bucket_
The bucket we should start from when we are pointing on a deleted bucket and we decide to do a ++.
Definition list.h:2236
bool isEnd() const
Returns a bool indicating whether the iterator points to the end of the list.
Definition list_tpl.h:725
ListBucket< Val > * _prev_current_bucket_
The bucket we should start from when we are pointing on a deleted bucket and we decide to do a –.
Definition list.h:2240
~ListConstIteratorSafe()
Class Desctructor.
Definition list_tpl.h:690
const List< Val > * _list_
The list the iterator is pointing to.
Definition list.h:2229
bool operator!=(const ListConstIteratorSafe< Val > &src) const
Checks whether two iterators point toward different elements.
Definition list_tpl.h:913
ListConstIteratorSafe< Val > operator-(difference_type i) noexcept
Returns a new iterator pointing to i preceding elements in the gum::List.
Definition list_tpl.h:906
ListConstIteratorSafe< Val > operator+(difference_type i) noexcept
Returns a new iterator pointing to i further elements in the gum::List.
Definition list_tpl.h:899
bool _null_pointing_
Indicates whether the bucket the iterator points to has been deleted.
Definition list.h:2243
ListConstIteratorSafe< Val > & operator+=(difference_type i) noexcept
Makes the iterator point to i elements further in the List.
Definition list_tpl.h:843
bool operator==(const ListConstIteratorSafe< Val > &src) const
Checks whether two iterators point toward the same elements.
Definition list_tpl.h:921
ListConstIteratorSafe< Val > & operator--() noexcept
Makes the iterator point to the preceding element in the List.
Definition list_tpl.h:853
void clear()
Makes the iterator point toward nothing.
Definition list_tpl.h:706
const Val * operator->() const
Dereferences the value pointed to by the iterator.
Definition list_tpl.h:929
Unsafe but fast const iterators for Lists.
Definition list.h:1449
ListBucket< Val > * _getBucket_() const noexcept
Returns the bucket the iterator is pointing to.
Definition list_tpl.h:238
ListBucket< Val > * _bucket_
The bucket in the chained list pointed to by the iterator.
Definition list.h:1671
std::ptrdiff_t difference_type
Types for STL compliance.
Definition list.h:1459
ListConstIterator< Val > & operator-=(difference_type i) noexcept
Makes the iterator point to i elements befor in the List.
Definition list_tpl.h:295
bool isEnd() const noexcept
Returns a bool indicating whether the iterator points to the end of the list.
Definition list_tpl.h:257
ListConstIterator< Val > & operator--() noexcept
Makes the iterator point to the preceding element in the List.
Definition list_tpl.h:285
void clear() noexcept
Makes the iterator point toward nothing.
Definition list_tpl.h:244
ListConstIterator< Val > & operator=(const ListConstIterator< Val > &src) noexcept
Copy operator.
Definition list_tpl.h:218
const Val * operator->() const
Dereferences the value pointed to by the iterator.
Definition list_tpl.h:333
ListConstIterator< Val > & operator++() noexcept
Makes the iterator point to the next element in the List.
Definition list_tpl.h:263
void setToEnd() noexcept
Positions the iterator to the end of the list.
Definition list_tpl.h:250
friend class List< Val >
Class List must be a friend because it uses the getBucket method to speed up some processes.
Definition list.h:1668
ListConstIterator() noexcept
Default constructor.
Definition list_tpl.h:155
ListConstIterator< Val > operator+(difference_type i) noexcept
Returns a new iterator pointing to i further elements in the gum::List.
Definition list_tpl.h:307
bool operator==(const ListConstIterator< Val > &src) const noexcept
Checks whether two iterators point toward the same elements.
Definition list_tpl.h:327
~ListConstIterator() noexcept
Class Desctructor.
Definition list_tpl.h:210
bool operator!=(const ListConstIterator< Val > &src) const noexcept
Checks whether two iterators point toward different elements.
Definition list_tpl.h:321
ListConstIterator< Val > & operator+=(difference_type i) noexcept
Makes the iterator point to i elements further in the List.
Definition list_tpl.h:273
ListConstIterator< Val > operator-(difference_type i) noexcept
Returns a new iterator pointing to i preceding elements in the gum::List.
Definition list_tpl.h:314
const Val & operator*() const
Gives access to the content of the iterator.
Definition list_tpl.h:340
Safe iterators for Lists.
Definition list.h:2318
std::ptrdiff_t difference_type
Types for STL compliance.
Definition list.h:2328
~ListIteratorSafe()
Class Desctructor.
Definition list_tpl.h:1016
ListIteratorSafe< Val > & operator+=(difference_type i) noexcept
Makes the iterator point to i elements further in the List.
Definition list_tpl.h:1041
ListIteratorSafe< Val > operator+(difference_type i) noexcept
Returns a new iterator pointing to i further elements in the gum::List.
Definition list_tpl.h:1064
ListIteratorSafe< Val > & operator-=(difference_type i) noexcept
Makes the iterator point to i elements befor in the List.
Definition list_tpl.h:1056
ListIteratorSafe< Val > & operator--() noexcept
Makes the iterator point to the preceding element in the List.
Definition list_tpl.h:1049
ListIteratorSafe< Val > & operator++() noexcept
Makes the iterator point to the next element in the List.
Definition list_tpl.h:1034
ListIteratorSafe< Val > operator-(difference_type i) noexcept
Returns a new iterator pointing to i preceding elements in the gum::List.
Definition list_tpl.h:1071
bool operator!=(const ListIteratorSafe< Val > &src) const
Checks whether two iterators point toward different elements.
Definition list_tpl.h:1028
ListIteratorSafe() noexcept
Default constructor.
Definition list_tpl.h:962
ListIteratorSafe< Val > & operator=(const ListIteratorSafe< Val > &src)
Copy operator.
Definition list_tpl.h:998
bool operator==(const ListIteratorSafe< Val > &src) const
Checks whether two iterators point toward the same elements.
Definition list_tpl.h:1022
Val & operator*()
Gives access to the content of the iterator.
Definition list_tpl.h:1090
Val * operator->()
Dereferences the value pointed to by the iterator.
Definition list_tpl.h:1078
Unsafe but fast iterators for Lists.
Definition list.h:1736
ListIterator< Val > & operator--() noexcept
Makes the iterator point to the preceding element in the List.
Definition list_tpl.h:448
ListIterator< Val > operator-(difference_type i) noexcept
Returns a new iterator pointing to i preceding elements in the gum::List.
Definition list_tpl.h:471
std::ptrdiff_t difference_type
Types for STL compliance.
Definition list.h:1746
ListIterator< Val > & operator=(const ListIterator< Val > &src) noexcept
Copy operator.
Definition list_tpl.h:399
bool operator==(const ListIterator< Val > &src) const noexcept
Checks whether two iterators point toward the same elements.
Definition list_tpl.h:421
ListIterator< Val > operator+(difference_type i) noexcept
Returns a new iterator pointing to i further elements in the gum::List.
Definition list_tpl.h:464
ListIterator< Val > & operator+=(difference_type i) noexcept
Makes the iterator point to i elements further in the List.
Definition list_tpl.h:441
ListIterator() noexcept
Default constructor.
Definition list_tpl.h:364
bool operator!=(const ListIterator< Val > &src) const noexcept
Checks whether two iterators point toward different elements.
Definition list_tpl.h:427
ListIterator< Val > & operator-=(difference_type i) noexcept
Makes the iterator point to i elements befor in the List.
Definition list_tpl.h:456
ListIterator< Val > & operator++() noexcept
Makes the iterator point to the next element in the List.
Definition list_tpl.h:433
const Val * operator->() const
Dereferences the value pointed to by the iterator.
Definition list_tpl.h:483
const Val & operator*() const
Gives access to the content of the iterator.
Definition list_tpl.h:495
~ListIterator() noexcept
Class destructor.
Definition list_tpl.h:415
Generic doubly linked lists.
Definition list.h:378
Val & emplaceFront(Args &&... args)
Emplace elements at the beginning of the chained list.
Definition list_tpl.h:1475
std::vector< const_iterator_safe * > _safe_iterators_
The list of "safe" iterators attached to the list.
Definition list.h:1262
Size size() const noexcept
Returns the number of elements in the list.
Definition list_tpl.h:1710
const iterator & rend() noexcept
Returns an unsafe iterator pointing just before the beginning of the List.
Definition list_tpl.h:1323
iterator rbegin()
Returns an unsafe iterator pointing to the last element of the List.
Definition list_tpl.h:1386
const_iterator cbegin() const
Returns an unsafe const iterator pointing to the beginning of the List.
Definition list_tpl.h:1347
Val & _pushFront_(ListBucket< Val > *new_elt)
Insert a bucket at the front of the list.
Definition list_tpl.h:1420
ListBucket< Val > * _createBucket_(const Val &val) const
Create a new bucket with a given value.
Definition list_tpl.h:1400
ListConstIteratorSafe< Val > const_iterator_safe
Types for STL compliance.
Definition list.h:392
bool operator!=(const List< Val > &src) const
Checks whether two lists are different (different elements or orders).
Definition list_tpl.h:1933
Val & pushFront(const Val &val)
Inserts a new element (a copy) at the beginning of the chained list.
Definition list_tpl.h:1455
friend class ListConstIterator< Val >
ListIterator should be a friend to optimize access to elements.
Definition list.h:1389
const const_iterator & cend() const noexcept
Returns an unsafe const iterator pointing to the end of the List.
Definition list_tpl.h:1287
location
Locations around iterators where insertions of new elements can take / place.
Definition list.h:397
Val & _insert_(const const_iterator_safe &iter, ListBucket< Val > *new_elt, location place)
Inserts a new bucket before or after the location pointed to by an iterator.
Definition list_tpl.h:1587
Val & push_front(Args &&... args)
An alias for pushFront used for STL compliance.
Definition list_tpl.h:1468
Val & back() const
Returns a reference to last element of a list, if any.
Definition list_tpl.h:1702
void _erase_(ListBucket< Val > *bucket)
Removes an element from a chained list.
Definition list_tpl.h:1725
void clear()
Deletes all the elements of a chained list.
Definition list_tpl.h:1147
friend class ListIteratorSafe< Val >
Definition list.h:1390
friend class ListConstIteratorSafe< Val >
Definition list.h:1391
Val & front() const
Returns a reference to first element of a list, if any.
Definition list_tpl.h:1694
std::string toString() const
Converts a list into a string.
Definition list_tpl.h:1828
ListBucket< Val > * _createEmplaceBucket_(Args &&... args) const
Create an emplace bucket.
Definition list_tpl.h:1413
const iterator_safe & rendSafe() noexcept
Returns a safe iterator pointing just before the beginning of the List.
Definition list_tpl.h:1311
iterator_safe beginSafe()
Returns a safe iterator pointing to the beginning of the List.
Definition list_tpl.h:1341
List< Mount > map(Mount(*f)(Val)) const
Creates a list of mountains from a list of val.
Definition list_tpl.h:1847
List< Val > & operator=(const List< Val > &src)
Copy operator.
Definition list_tpl.h:1231
Val & push_back(Args &&... args)
An alias for pushBack used for STL compliance.
Definition list_tpl.h:1494
gum::Instantiation *& pushBack(const gum::Instantiation *&val)
Definition list_tpl.h:1481
ListBucket< Val > * _getIthBucket_(Size i) const noexcept
Returns the bucket corresponding to the ith position in the list.
Definition list_tpl.h:1520
Val & emplaceBack(Args &&... args)
Emplace elements at the end of the chained list.
Definition list_tpl.h:1501
const_iterator_safe cbeginSafe() const
Returns a safe const iterator pointing to the beginning of the List.
Definition list_tpl.h:1335
ListBucket< Val > * _deb_list_
A pointer on the first element of the chained list.
Definition list.h:1253
const iterator & end() noexcept
Returns an unsafe iterator pointing to the end of the List.
Definition list_tpl.h:1293
Val & _pushBack_(ListBucket< Val > *new_elt)
Insert a bucket at the end of the list.
Definition list_tpl.h:1437
void popBack()
Removes the last element of a List, if any.
Definition list_tpl.h:1810
List()
A basic constructor that creates an empty list.
Definition list_tpl.h:1167
const const_iterator & crend() const noexcept
Returns an unsafe const iterator pointing just before the beginning of the List.
Definition list_tpl.h:1317
ListBucket< Val > * _getBucket_(const Val &val) const noexcept
Returns the bucket corresponding to a given value.
Definition list_tpl.h:1784
void swap(List &other_list)
Swap the current list with another one.
Definition list_tpl.h:1957
ListIteratorSafe< Val > iterator_safe
Types for STL compliance.
Definition list.h:391
iterator begin()
Returns an unsafe iterator pointing to the beginning of the List.
Definition list_tpl.h:1353
void eraseAllVal(const Val &val)
erases all the elements encountered with a given value
Definition list_tpl.h:1799
Val & _insertAfter_(ListBucket< Val > *new_elt, ListBucket< Val > *current_elt)
Insert a new bucket after another one.
Definition list_tpl.h:1551
Val & insert(const Val &val)
Inserts a new element at the end of the chained list (alias of pushBack).
Definition list_tpl.h:1508
bool empty() const noexcept
Returns a boolean indicating whether the chained list is empty.
Definition list_tpl.h:1822
Size _nb_elements_
The number of elements in the list.
Definition list.h:1259
void _copy_elements_(const List< Val > &src)
A function used to perform copies of elements of Lists.
Definition list_tpl.h:1108
bool exists(const Val &val) const
Checks whether there exists a given element in the list.
Definition list_tpl.h:1716
const_iterator_safe crbeginSafe() const
Returns a safe const iterator pointing to the last element of the List.
Definition list_tpl.h:1365
Val & operator+=(const Val &val)
Inserts a new element at the end of the list (alias of pushBack).
Definition list_tpl.h:1906
~List()
Class destructor.
Definition list_tpl.h:1220
Val & emplace(const const_iterator &iter, Args &&... args)
Emplace a new element before a given iterator.
Definition list_tpl.h:1681
void popFront()
Removes the first element of a List, if any.
Definition list_tpl.h:1816
const_iterator crbegin() const
Returns an unsafe const iterator pointing to the last element of the List.
Definition list_tpl.h:1379
const const_iterator_safe & cendSafe() const noexcept
Returns a safe const iterator pointing to the end of the List.
Definition list_tpl.h:1275
void eraseByVal(const Val &val)
erases the first element encountered with a given value.
Definition list_tpl.h:1793
bool operator==(const List< Val > &src) const
Checks whether two lists are identical (same elements in the same order).
Definition list_tpl.h:1919
iterator_safe rbeginSafe()
Returns a safe iterator pointing to the last element of the List.
Definition list_tpl.h:1372
Val & _insertBefore_(ListBucket< Val > *new_elt, ListBucket< Val > *current_elt)
Insert a new bucket before another one.
Definition list_tpl.h:1534
Val & operator[](const Size i)
Returns the ith element in the current chained list.
Definition list_tpl.h:1939
ListConstIterator< Val > const_iterator
Types for STL compliance.
Definition list.h:390
const const_iterator_safe & crendSafe() const noexcept
Return a safe const iterator pointing just before the beginning of the List.
Definition list_tpl.h:1305
ListBucket< Val > * _end_list_
A pointer on the last element of the chained list.
Definition list.h:1256
const iterator_safe & endSafe() noexcept
Returns a safe iterator pointing to the end of the List.
Definition list_tpl.h:1281
void erase(Size i)
Erases the ith element of the List (the first one is in position 0).
Definition list_tpl.h:1763
Exception : the element we looked for cannot be found.
Exception : generic error on iterator.
#define GUM_ERROR(type, msg)
Definition exceptions.h:76
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition types.h:74
Size Idx
Type for indexes.
Definition types.h:79
Generic class for manipulating lists.
#define GUM_DEFAULT_ITERATOR_NUMBER
Definition list.h:63
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
std::ostream & operator<<(std::ostream &stream, const AVLTree< Val, Cmp > &tree)
display the content of a tree
ListConstIterator< Val >::difference_type operator-(const ListConstIterator< Val > &iter1, const ListConstIterator< Val > &iter2)
For STL compliance, a distance operator.
Definition list_tpl.h:348
bool operator==(const HashTableIteratorSafe< Key, Val > &from) const noexcept
Checks whether two iterators are pointing toward equal elements.
STL namespace.