aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
list_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 /**
23  * @file
24  * @brief template implementation of chained lists
25  *
26  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
27  */
28 
29 // to ease parser
30 #include <agrum/tools/core/list.h>
31 
32 namespace gum {
33 
34  // ===========================================================================
35  // ===========================================================================
36  // === BUCKET IMPLEMENTATION ===
37  // ===========================================================================
38  // ===========================================================================
39 
40  // default constructor
41  template < typename Val >
42  INLINE ListBucket< Val >::ListBucket(const Val& v) : _val_{v} {
43  // for debugging purposes
45  }
46 
47  // constructor for Val rvalues
48  template < typename Val >
49  INLINE ListBucket< Val >::ListBucket(Val&& v) noexcept : _val_{std::move(v)} {
50  // for debugging purposes
52  }
53 
54  // emplace constructor
55  template < typename Val >
56  template < typename... Args >
58  _val_(std::forward< Args >(args)...) {
59  // for debugging purposes
61  }
62 
63  // copy constructor
64  template < typename Val >
66  // for debugging purposes
68  }
69 
70  // copy operator
71  template < typename Val >
73  // for debugging purposes
75 
76  // no need to avoid self assignment
77  _val_ = src._val_;
78  return *this;
79  }
80 
81  // WARNING: during its deletion, the bucket does not take care of properly
82  // re-chaining the chained list. This should be done by the Lists themselves
83  template < typename Val >
85  // for debugging purposes
87  }
88 
89  // equality check
90  template < typename Val >
91  INLINE bool ListBucket< Val >::operator==(const ListBucket< Val >& src) const {
92  return (src._val_ == _val_);
93  }
94 
95  // inequality check
96  template < typename Val >
97  INLINE bool ListBucket< Val >::operator!=(const ListBucket< Val >& src) const {
98  return (src._val_ != _val_);
99  }
100 
101  // dereferencing operator
102  template < typename Val >
103  INLINE const Val& ListBucket< Val >::operator*() const noexcept {
104  return _val_;
105  }
106 
107  // dereferencing operator
108  template < typename Val >
109  INLINE Val& ListBucket< Val >::operator*() noexcept {
110  return _val_;
111  }
112 
113  // returns the bucket toward the next element
114  template < typename Val >
115  INLINE const ListBucket< Val >* ListBucket< Val >::next() const noexcept {
116  return _next_;
117  }
118 
119  // returns the bucket toward the preceding element
120  template < typename Val >
121  INLINE const ListBucket< Val >* ListBucket< Val >::previous() const noexcept {
122  return _prev_;
123  }
124 
125  // ===========================================================================
126  // ===========================================================================
127  // === UNSAFE_CONST_LIST_ITERATOR IMPLEMENTATION ===
128  // ===========================================================================
129  // ===========================================================================
130 
131  // default constructor
132  template < typename Val >
134  // for debugging purposes
136  }
137 
138  // default constructor
139  template < typename Val >
140  template < typename Alloc >
143  // for debugging purposes
145  }
146 
147  // copy constructor
148  template < typename Val >
151  // for debugging purposes
153  }
154 
155  // move constructor
156  template < typename Val >
159  // for debugging purposes
161  }
162 
163  // Constructor for an iterator pointing to the \e ind_eltth element of a
164  // List.
165  template < typename Val >
167  // for debugging purposes
169 
170  // check if the index ind_elt passed as parameter is valid
171  if (ind_elt >= theList._nb_elements_) {
172  GUM_ERROR(UndefinedIteratorValue, "Not enough elements in the list")
173  }
174 
175  // check if it is faster to find the indexth element from the start or
176  // from the end of the list
177  if (ind_elt < (theList._nb_elements_ >> 1)) {
178  // find the element we shall point to src the start of the list
180  } else {
181  // find the element we shall point to src the end of the list
183  --ind_elt, _bucket_ = _bucket_->_prev_) {}
184  }
185  }
186 
187  // Destructor
188  template < typename Val >
190  // for debugging purposes
192  }
193 
194  // Copy operator
195  template < typename Val >
198  // for debugging purposes
200 
202  return *this;
203  }
204 
205  // move operator
206  template < typename Val >
209  // for debugging purposes
212  return *this;
213  }
214 
215  // returns the bucket the iterator is pointing to
216  template < typename Val >
218  return _bucket_;
219  }
220 
221  // Makes the iterator point toward nothing
222  template < typename Val >
223  INLINE void ListConstIterator< Val >::clear() noexcept {
224  _bucket_ = nullptr;
225  }
226 
227  // positions the iterator to the end of the list
228  template < typename Val >
229  INLINE void ListConstIterator< Val >::setToEnd() noexcept {
230  _bucket_ = nullptr;
231  }
232 
233  // returns a bool indicating whether the iterator points to the end of the
234  // list
235  template < typename Val >
236  INLINE bool ListConstIterator< Val >::isEnd() const noexcept {
237  return (_bucket_ == nullptr);
238  }
239 
240  // makes the iterator point to the next element in the List
241  template < typename Val >
243  // if we are pointing to an element of the chained list, just
244  // point on the next bucket in this list
245  if (_bucket_ != nullptr) { _bucket_ = _bucket_->_next_; }
246 
247  return *this;
248  }
249 
250  // makes the iterator point to the next element in the List
251  template < typename Val >
253  typename ListConstIterator< Val >::difference_type i) noexcept {
254  if (i >= 0) {
255  for (; i && (_bucket_ != nullptr); --i, _bucket_ = _bucket_->_next_) {}
256  } else {
257  for (; i && (_bucket_ != nullptr); ++i, _bucket_ = _bucket_->_prev_) {}
258  }
259  return *this;
260  }
261 
262  // makes the iterator point to the preceding element in the List
263  template < typename Val >
265  // if we are pointing to an element of the chained list, just
266  // point on the preceding bucket in this list
267  if (_bucket_ != nullptr) { _bucket_ = _bucket_->_prev_; }
268 
269  return *this;
270  }
271 
272  // makes the iterator point to i elements before in the list
273  template < typename Val >
275  typename ListConstIterator< Val >::difference_type i) noexcept {
276  if (i >= 0) {
277  for (; i && (_bucket_ != nullptr); --i, _bucket_ = _bucket_->_prev_) {}
278  } else {
279  for (; i && (_bucket_ != nullptr); ++i, _bucket_ = _bucket_->_next_) {}
280  }
281  return *this;
282  }
283 
284  // returns a new iterator
285  template < typename Val >
287  typename ListConstIterator< Val >::difference_type i) noexcept {
288  return ListConstIterator< Val >(*this) += i;
289  }
290 
291  // returns a new iterator
292  template < typename Val >
294  typename ListConstIterator< Val >::difference_type i) noexcept {
295  return ListConstIterator< Val >(*this) -= i;
296  }
297 
298  // checks whether two iterators point toward different elements
299  template < typename Val >
300  INLINE bool
301  ListConstIterator< Val >::operator!=(const ListConstIterator< Val >& src) const noexcept {
302  return (_bucket_ != src._bucket_);
303  }
304 
305  // checks whether two iterators point toward the same elements.
306  template < typename Val >
307  INLINE bool
308  ListConstIterator< Val >::operator==(const ListConstIterator< Val >& src) const noexcept {
309  return (_bucket_ == src._bucket_);
310  }
311 
312  // dereferences the value pointed to by the iterator
313  template < typename Val >
314  INLINE const Val* ListConstIterator< Val >::operator->() const {
315  if (_bucket_ != nullptr)
316  return &(_bucket_->_val_);
317  else {
318  GUM_ERROR(UndefinedIteratorValue, "Accessing a NULL object")
319  }
320  }
321 
322  // gives access to the content of the iterator
323  template < typename Val >
324  INLINE const Val& ListConstIterator< Val >::operator*() const {
325  if (_bucket_ != nullptr)
326  return _bucket_->_val_;
327  else {
328  GUM_ERROR(UndefinedIteratorValue, "Accessing a NULL object")
329  }
330  }
331 
332  // for STL compliance, a distance operator
333  template < typename Val >
336  typename ListConstIterator< Val >::difference_type res = 0;
337 
338  for (ListConstIterator< Val > iter3 = iter2; iter1 != iter3; ++iter3, ++res) {}
339 
340  return res;
341  }
342 
343  // ===========================================================================
344  // ===========================================================================
345  // === UNSAFE_LIST_ITERATOR IMPLEMENTATION ===
346  // ===========================================================================
347  // ===========================================================================
348 
349  // basic constructor
350  template < typename Val >
353  }
354 
355  // constructor for a begin
356  template < typename Val >
357  template < typename Alloc >
361  }
362 
363  // copy constructor
364  template < typename Val >
368  }
369 
370  // move constructor
371  template < typename Val >
375  }
376 
377  // Constructor for an iterator pointing to the \e ind_eltth element of a
378  // List.
379  template < typename Val >
383  }
384 
385  // Copy operator
386  template < typename Val >
388  ListIterator< Val >::operator=(const ListIterator< Val >& src) noexcept {
391  return *this;
392  }
393 
394  // move operator
395  template < typename Val >
399  return *this;
400  }
401 
402  // Destructor
403  template < typename Val >
406  }
407 
408  // makes the iterator point to the next element in the List
409  template < typename Val >
412  return *this;
413  }
414 
415  // makes the iterator point to i elements further in the List
416  template < typename Val >
418  ListIterator< Val >::operator+=(typename ListIterator< Val >::difference_type i) noexcept {
420  return *this;
421  }
422 
423  // makes the iterator point to the preceding element in the List
424  template < typename Val >
427  return *this;
428  }
429 
430  // makes the iterator point to i elements before in the List
431  template < typename Val >
433  ListIterator< Val >::operator-=(typename ListIterator< Val >::difference_type i) noexcept {
435  return *this;
436  }
437 
438  // returns a new iterator
439  template < typename Val >
441  ListIterator< Val >::operator+(typename ListIterator< Val >::difference_type i) noexcept {
442  return ListIterator< Val >(*this) += i;
443  }
444 
445  // returns a new iterator
446  template < typename Val >
448  ListIterator< Val >::operator-(typename ListIterator< Val >::difference_type i) noexcept {
449  return ListIterator< Val >(*this) -= i;
450  }
451 
452  // dereferences the value pointed to by the iterator
453  template < typename Val >
455  return const_cast< Val* >(ListConstIterator< Val >::operator->());
456  }
457 
458  // gives access to the content of the iterator
459  template < typename Val >
461  return const_cast< Val& >(ListConstIterator< Val >::operator*());
462  }
463 
464  // ===========================================================================
465  // ===========================================================================
466  // === SAFE LIST CONST ITERATOR IMPLEMENTATION ===
467  // ===========================================================================
468  // ===========================================================================
469 
470  // basic constructor
471  template < typename Val >
473  // for debugging purposes
475  }
476 
477  // Constructor for a begin
478  template < typename Val >
479  template < typename Alloc >
481  _list_{reinterpret_cast< const List< Val, std::allocator< Val > >* >(&theList)},
483  // for debugging purposes
485 
486  // add the iterator to the list of safe iterators
488  }
489 
490  // copy constructor
491  template < typename Val >
492  INLINE
494  _list_{src._list_},
497  // for debugging purposes
499 
500  // add the iterator to the list of safe iterators
501  if (_list_ != nullptr) _list_->_safe_iterators_.push_back(this);
502  }
503 
504  // Constructor for an iterator pointing to the \e ind_eltth element of a
505  // List.
506  template < typename Val >
507  template < typename Alloc >
509  Size ind_elt) :
510  _list_{reinterpret_cast< const List< Val, std::allocator< Val > >* >(&theList)} {
511  // for debugging purposes
513 
514  // check if the index ind_elt passed as parameter is valid
515  if (ind_elt >= _list_->_nb_elements_) {
516  GUM_ERROR(UndefinedIteratorValue, "Not enough elements in the list")
517  }
518 
519  // check if it is faster to find the indexth element src the start or
520  // src the end of the list
521  if (ind_elt < (_list_->_nb_elements_ >> 1)) {
522  // find the element we shall point to src the start of the list
524  } else {
525  // find the element we shall point to src the end of the list
527  --ind_elt, _bucket_ = _bucket_->_prev_) {}
528  }
529 
530  // add the iterator to the list of safe iterators
532  }
533 
534  // move constructor
535  template < typename Val >
539  // for debugging purposes
541 
542  if (_list_ != nullptr) {
543  // substitute src by this in the list of safe iterators
545 
546  for (auto ptr = vect.rbegin(); ptr != vect.rend(); --ptr) {
547  if (*ptr == &src) {
548  *ptr = this;
549  break;
550  }
551  }
552 
553  src._list_ = nullptr;
554  src._bucket_ = nullptr;
555  src._null_pointing_ = false;
556  }
557  }
558 
559  // remove the iterator for its list' safe iterators list
560  template < typename Val >
562  // find where the iterator is
564 
565  for (auto i = vect.size() - 1; i >= 0; --i) {
566  if (vect[i] == this) {
567  vect.erase(vect.begin() + i);
568  break;
569  }
570  }
571  }
572 
573  // Copy operator
574  template < typename Val >
577  // avoid self assignment
578  if (this != &src) {
579  // for debugging purposes
581 
582  // check if src and this belong to the same list. If this is not
583  // the case, we shall remove this from its iterator's list and
584  // put it into src's list one.
585  if (_list_ && (src._list_ != _list_)) {
587  _list_ = nullptr;
588  }
589 
590  // if necessary, put this into the same list of safe iterators as src
591  if (src._list_ && (src._list_ != _list_)) {
592  try {
594  } catch (...) {
595  _list_ = nullptr;
596  _bucket_ = nullptr;
597  _null_pointing_ = false;
598  throw;
599  }
600  }
601 
602  _list_ = src._list_;
607  }
608 
609  return *this;
610  }
611 
612  // move operator
613  template < typename Val >
616  // avoid self assignment
617  if (this != &src) {
618  // for debugging purposes
620 
621  // if the two iterators do not point to the same list, remove
622  // the current iterator from its safe iterators list
623  if ((_list_ != nullptr) && (src._list_ != _list_)) {
625  _list_ = nullptr;
626  }
627 
628  // now if src points to a list, put this at its location
629  if ((src._list_ != nullptr)) {
631  Idx index_src = Size(vect.size()) - 1;
632 
633  for (;; --index_src) {
634  if (vect[index_src] == &src) { break; }
635  }
636 
637  if (_list_ == nullptr) {
638  vect[index_src] = this;
639  } else {
641  }
642  }
643 
644  _list_ = src._list_;
649 
650  src._list_ = nullptr;
651  src._bucket_ = nullptr;
652  src._null_pointing_ = false;
653  }
654 
655  return *this;
656  }
657 
658  // Destructor
659  template < typename Val >
661  // for debugging purposes
663 
664  // remove the iterator src the table's iterator list
666  }
667 
668  // returns the bucket the iterator is pointing to
669  template < typename Val >
671  return _bucket_;
672  }
673 
674  // Makes the iterator point toward nothing
675  template < typename Val >
677  // remove the iterator src the list's iterator list
679 
680  // set its list as well as the element it points to to nullptr
681  _list_ = nullptr;
682  _bucket_ = nullptr;
683  _null_pointing_ = false;
684  }
685 
686  // positions the iterator to the end of the list
687  template < typename Val >
689  clear();
690  }
691 
692  // returns a bool indicating whether the iterator points to the end of the
693  // list
694  template < typename Val >
696  return _null_pointing_
697  ? (_next_current_bucket_ == nullptr) && (_prev_current_bucket_ == nullptr)
698  : (_bucket_ == nullptr);
699  }
700 
701  // makes the iterator point to the next element in the List
702  template < typename Val >
704  // check if we are pointing to something that has been deleted
705  if (_null_pointing_) {
706  _null_pointing_ = false;
707 
708  // if we are pointing to an element of the chained list that has been
709  // deleted
710  // but that has a next element, just point on the latter
711  if (_next_current_bucket_ != nullptr) {
713  return *this;
714  }
715 
716  // here we were pointing on an extremity of the list (either end or rend)
717  // if prev_current_bucket is not null, then we are at rend and doing
718  // a ++ shall now point to the beginning of the list
719  if (_prev_current_bucket_ != nullptr) {
721  return *this;
722  }
723 
724  // here, we are at the end of the chained list, hence we shall remain at
725  // end
726  _bucket_ = nullptr;
727  return *this;
728  } else {
729  // if we are pointing to an element of the chained list, just
730  // point on the next bucket in this list
731  if (_bucket_ != nullptr) { _bucket_ = _bucket_->_next_; }
732 
733  return *this;
734  }
735  }
736 
737  // makes the iterator point to i elements before in the List
738  template < typename Val >
740  // check if we are pointing to something that has been deleted
741  if (_null_pointing_) {
742  _null_pointing_ = false;
743 
744  // if we are pointing to an element of the chained list that has been
745  // deleted
746  // but that has a preceding element, just point on the latter
747  if (_prev_current_bucket_ != nullptr) {
749  } else {
750  // here we were pointing on an extremity of the list (either end or
751  // rend)
752  // if next_current_bucket is not null, then we are at end and doing
753  // a -- shall now point to the beginning of the list
754  if (_next_current_bucket_ != nullptr) {
756  } else {
757  // here, we are at the rend of the chained list, hence we shall remain
758  // at rend
759  _bucket_ = nullptr;
760  return *this;
761  }
762  }
763  } else {
764  // if we are pointing to an element of the chained list, just
765  // point on the preceding bucket in this list
766  if (_bucket_ != nullptr) { _bucket_ = _bucket_->_prev_; }
767  }
768 
769  for (--i; i && (_bucket_ != nullptr); --i, _bucket_ = _bucket_->_prev_) {}
770 
771  return *this;
772  }
773 
774  // makes the iterator point to the next element in the List
775  template < typename Val >
777  // check if we are pointing to something that has been deleted
778  if (_null_pointing_) {
779  _null_pointing_ = false;
780 
781  // if we are pointing to an element of the chained list that has been
782  // deleted
783  // but that has a next element, just point on the latter
784  if (_next_current_bucket_ != nullptr) {
786  } else {
787  // here we were pointing on an extremity of the list (either end or
788  // rend)
789  // if prev_current_bucket is not null, then we are at rend and doing
790  // a ++ shall now point to the beginning of the list
791  if (_prev_current_bucket_ != nullptr) {
793  } else {
794  // here, we are at the end of the chained list, hence we shall
795  // remain at end
796  _bucket_ = nullptr;
797  return *this;
798  }
799  }
800  } else {
801  // if we are pointing to an element of the chained list, just
802  // point on the next bucket in this list
803  if (_bucket_ != nullptr) { _bucket_ = _bucket_->_next_; }
804  }
805 
806  for (--i; i && (_bucket_ != nullptr); --i, _bucket_ = _bucket_->_next_) {}
807 
808  return *this;
809  }
810 
811  // makes the iterator point to the next element in the List
812  template < typename Val >
814  typename ListConstIteratorSafe< Val >::difference_type i) noexcept {
815  if (!i) return *this;
816 
817  if (i < 0)
818  return _opMinus_(-i);
819  else
820  return _opPlus_(i);
821  }
822 
823  // makes the iterator point to the preceding element in the List
824  template < typename Val >
826  // check if we are pointing to something that has been deleted
827  if (_null_pointing_) {
828  _null_pointing_ = false;
829 
830  // if we are pointing to an element of the chained list that has been
831  // deleted
832  // but that has a preceding element, just point on the latter
833  if (_prev_current_bucket_ != nullptr) {
835  return *this;
836  }
837 
838  // here we were pointing on an extremity of the list (either end or rend)
839  // if next_current_bucket is not null, then we are at end and doing
840  // a -- shall now point to the beginning of the list
841  if (_next_current_bucket_ != nullptr) {
843  return *this;
844  }
845 
846  // here, we are at the rend of the chained list, hence we shall remain
847  // at rend
848  _bucket_ = nullptr;
849  return *this;
850  } else {
851  // if we are pointing to an element of the chained list, just
852  // point on the preceding bucket in this list
853  if (_bucket_ != nullptr) { _bucket_ = _bucket_->_prev_; }
854 
855  return *this;
856  }
857  }
858 
859  // makes the iterator point to i elements before in the List
860  template < typename Val >
862  typename ListConstIteratorSafe< Val >::difference_type i) noexcept {
863  if (!i) return *this;
864 
865  if (i < 0)
866  return _opPlus_(-i);
867  else
868  return _opMinus_(i);
869  }
870 
871  // returns a new iterator
872  template < typename Val >
874  typename ListConstIteratorSafe< Val >::difference_type i) noexcept {
875  return ListConstIteratorSafe< Val >(*this) += i;
876  }
877 
878  // returns a new iterator
879  template < typename Val >
881  typename ListConstIteratorSafe< Val >::difference_type i) noexcept {
882  return ListConstIteratorSafe< Val >(*this) -= i;
883  }
884 
885  // checks whether two iterators point toward different elements
886  template < typename Val >
887  INLINE bool
891  : (_bucket_ != src._bucket_);
892  }
893 
894  // checks whether two iterators point toward the same elements.
895  template < typename Val >
896  INLINE bool
900  : (_bucket_ == src._bucket_);
901  }
902 
903  // dereferences the value pointed to by the iterator
904  template < typename Val >
905  INLINE const Val* ListConstIteratorSafe< Val >::operator->() const {
906  if (_bucket_ != nullptr)
907  return &(_bucket_->_val_);
908  else {
909  GUM_ERROR(UndefinedIteratorValue, "Accessing a NULL object")
910  }
911  }
912 
913  // gives access to the content of the iterator
914  template < typename Val >
916  if (_bucket_ != nullptr)
917  return _bucket_->_val_;
918  else {
919  GUM_ERROR(UndefinedIteratorValue, "Accessing a NULL object")
920  }
921  }
922 
923  // for STL compliance, a distance operator
924  template < typename Val >
927  const ListConstIteratorSafe< Val >& iter2) {
928  typename ListConstIteratorSafe< Val >::difference_type res = 0;
930 
931  for (; iter1 != iter3; ++iter3, ++res) {}
932 
933  return res;
934  }
935 
936  // ===========================================================================
937  // ===========================================================================
938  // === LIST ITERATOR IMPLEMENTATION ===
939  // ===========================================================================
940  // ===========================================================================
941 
942  // basic constructor
943  template < typename Val >
946  }
947 
948  // constructor for a begin
949  template < typename Val >
950  template < typename Alloc >
954  }
955 
956  // copy constructor
957  template < typename Val >
961  }
962 
963  // Constructor for an iterator pointing to the \e ind_eltth element of a
964  // List.
965  template < typename Val >
966  template < typename Alloc >
968  Size ind_elt) :
971  }
972 
973  // move constructor
974  template < typename Val >
978  }
979 
980  // Copy operator
981  template < typename Val >
984  // for debugging purposes
987  return *this;
988  }
989 
990  // move operator
991  template < typename Val >
994  // for debugging purposes
997  return *this;
998  }
999 
1000  // Destructor
1001  template < typename Val >
1004  }
1005 
1006  // makes the iterator point to the next element in the List
1007  template < typename Val >
1010  return *this;
1011  }
1012 
1013  // makes the iterator point to the next element in the List
1014  template < typename Val >
1016  typename ListIteratorSafe< Val >::difference_type i) noexcept {
1018  return *this;
1019  }
1020 
1021  // makes the iterator point to the preceding element in the List
1022  template < typename Val >
1025  return *this;
1026  }
1027 
1028  // makes the iterator point to the preceding element in the List
1029  template < typename Val >
1031  typename ListIteratorSafe< Val >::difference_type i) noexcept {
1033  return *this;
1034  }
1035 
1036  // returns a new iterator
1037  template < typename Val >
1039  typename ListIteratorSafe< Val >::difference_type i) noexcept {
1040  return ListIteratorSafe< Val >(*this) += i;
1041  }
1042 
1043  // returns a new iterator
1044  template < typename Val >
1046  typename ListIteratorSafe< Val >::difference_type i) noexcept {
1047  return ListIteratorSafe< Val >(*this) -= i;
1048  }
1049 
1050  // dereferences the value pointed to by the iterator
1051  template < typename Val >
1053  return const_cast< Val* >(ListConstIteratorSafe< Val >::operator->());
1054  }
1055 
1056  // gives access to the content of the iterator
1057  template < typename Val >
1059  return const_cast< Val& >(ListConstIteratorSafe< Val >::operator*());
1060  }
1061 
1062  // ===========================================================================
1063  // ===========================================================================
1064  // === LIST IMPLEMENTATION ===
1065  // ===========================================================================
1066  // ===========================================================================
1067 
1068  // a function used to perform copies of elements of Lists
1069  template < typename Val, typename Alloc >
1070  template < typename OtherAlloc >
1072  ListBucket< Val >* ptr;
1073  ListBucket< Val >* old_ptr = nullptr;
1074  ListBucket< Val >* new_elt = nullptr;
1075 
1076  // copy src's list
1077  try {
1078  for (ptr = src._deb_list_; ptr != nullptr; ptr = ptr->_next_) {
1079  // create a copy bucket
1081 
1082  try {
1084  } catch (...) {
1086  throw;
1087  }
1088 
1089  // rechain properly the new list (the next field is already initialized
1090  // with nullptr)
1091  new_elt->_prev_ = old_ptr;
1092 
1093  if (old_ptr)
1094  old_ptr->_next_ = new_elt;
1095  else
1096  _deb_list_ = new_elt;
1097 
1098  old_ptr = new_elt;
1099  }
1100  } catch (...) {
1101  // problem: we could not allocate an element in the list => we delete
1102  // the elements created so far and we throw an exception
1103  for (; _deb_list_ != nullptr; _deb_list_ = const_cast< ListBucket< Val >* >(ptr)) {
1104  ptr = _deb_list_->_next_;
1107  }
1108 
1109  _deb_list_ = nullptr;
1110  throw;
1111  }
1112 
1113  // update properly the end of the chained list and the number of elements
1114  _end_list_ = old_ptr;
1116  }
1117 
1118  // deletes all the elements of a chained list.
1119  template < typename Val, typename Alloc >
1120  void List< Val, Alloc >::clear() {
1121  // first we update all the safe iterators of the list : they should now
1122  // point to end/rend
1123  for (const auto ptr_iter: _safe_iterators_) {
1124  ptr_iter->clear();
1125  }
1126 
1127  // clear all the values
1128  for (ListBucket< Val >*ptr = _deb_list_, *next_ptr = nullptr; ptr != nullptr; ptr = next_ptr) {
1129  next_ptr = ptr->_next_;
1132  }
1133 
1134  _nb_elements_ = 0;
1135  _deb_list_ = nullptr;
1136  _end_list_ = nullptr;
1137  }
1138 
1139  // A basic constructor that creates an empty list
1140  template < typename Val, typename Alloc >
1142  // for debugging purposes
1144 
1145  // reserve space for only the default number of iterators
1147  }
1148 
1149  // Copy constructor
1150  template < typename Val, typename Alloc >
1151  INLINE List< Val, Alloc >::List(const List< Val, Alloc >& src) {
1152  // for debugging purposes
1153  GUM_CONS_CPY(List);
1154 
1155  // copy the elements
1157 
1158  // reserve space for only the default number of iterators
1160  }
1161 
1162  // generalized copy constructor
1163  template < typename Val, typename Alloc >
1164  template < typename OtherAlloc >
1166  // for debugging purposes
1167  GUM_CONS_CPY(List);
1168 
1169  // copy the elements
1171 
1172  // reserve space for only the default number of iterators
1174  }
1175 
1176  // move constructor
1177  template < typename Val, typename Alloc >
1182  std::move(src._alloc_bucket_)} {
1183  // for debugging purposes
1184  GUM_CONS_MOV(List);
1185 
1186  src._deb_list_ = nullptr;
1187  src._end_list_ = nullptr;
1188  src._nb_elements_ = 0;
1190  }
1191 
1192  // initializer_list constructor
1193  template < typename Val, typename Alloc >
1195  // for debugging purposes
1197 
1198  // adding all the elements
1199  for (const auto& val: list) {
1200  pushBack(val);
1201  }
1202 
1203  // reserve space for only the default number of iterators
1205  }
1206 
1207  // Destructor
1208  template < typename Val, typename Alloc >
1210  // for debugging (although this program is bug-free)
1212 
1213  // we detach all the safe iterators attached to the current List and we
1214  // remove all the elements from the list
1215  clear();
1216  }
1217 
1218  // Copy operator. The List iterator's list is not shared with that of \e src.
1219  template < typename Val, typename Alloc >
1220  INLINE List< Val, Alloc >& List< Val, Alloc >::operator=(const List< Val, Alloc >& src) {
1221  // avoid self assignment
1222  if (this != &src) {
1223  // for debugging purposes
1224  GUM_OP_CPY(List);
1225 
1226  // remove the old content of 'this' and update accordingly the iterators
1227  clear();
1228 
1229  // perform the copy
1231  }
1232 
1233  return *this;
1234  }
1235 
1236  // Generalized copy operator.
1237  template < typename Val, typename Alloc >
1238  template < typename OtherAlloc >
1240  // avoid self assignment
1241  if (this != reinterpret_cast< List< Val, Alloc >* >(&src)) {
1242  // for debugging purposes
1243  GUM_OP_CPY(List);
1244 
1245  // remove the old content of 'this' and update accordingly the iterators
1246  clear();
1247 
1248  // perform the copy
1250  }
1251 
1252  return *this;
1253  }
1254 
1255  // move operator
1256  template < typename Val, typename Alloc >
1258  // avoid self assignment
1259  if (this != &src) {
1260  // for debugging purposes
1261  GUM_OP_MOV(List);
1262 
1263  // remove the old content of 'this' and update accordingly the iterators
1264  clear();
1265 
1266  // perform the move
1272 
1273  src._deb_list_ = nullptr;
1274  src._end_list_ = nullptr;
1275  src._nb_elements_ = 0;
1277  }
1278 
1279  return *this;
1280  }
1281 
1282  // the iterator pointing to the end of the List
1283  template < typename Val, typename Alloc >
1284  INLINE const ListConstIteratorSafe< Val >& List< Val, Alloc >::cendSafe() const noexcept {
1285  return *(reinterpret_cast< const ListConstIteratorSafe< Val >* >(_list_end_safe_));
1286  }
1287 
1288  // the iterator pointing to the end of the List
1289  template < typename Val, typename Alloc >
1290  INLINE const ListIteratorSafe< Val >& List< Val, Alloc >::endSafe() noexcept {
1291  return *(reinterpret_cast< const ListIteratorSafe< Val >* >(_list_end_safe_));
1292  }
1293 
1294  // the iterator pointing to the end of the List
1295  template < typename Val, typename Alloc >
1296  INLINE const ListConstIterator< Val >& List< Val, Alloc >::cend() const noexcept {
1297  return *(reinterpret_cast< const ListConstIterator< Val >* >(_list_end_));
1298  }
1299 
1300  // the iterator pointing to the end of the List
1301  template < typename Val, typename Alloc >
1302  INLINE const ListIterator< Val >& List< Val, Alloc >::end() noexcept {
1303  return *(reinterpret_cast< const ListIterator< Val >* >(_list_end_));
1304  }
1305 
1306  // the iterator pointing to the end of the List
1307  template < typename Val, typename Alloc >
1308  INLINE const ListConstIterator< Val >& List< Val, Alloc >::end() const noexcept {
1309  return *(reinterpret_cast< const ListConstIterator< Val >* >(_list_end_));
1310  }
1311 
1312  // the iterator pointing to the rend (just before the beginning) of the List
1313  template < typename Val, typename Alloc >
1314  INLINE const ListConstIteratorSafe< Val >& List< Val, Alloc >::crendSafe() const noexcept {
1315  return *(reinterpret_cast< const ListConstIteratorSafe< Val >* >(_list_end_safe_));
1316  }
1317 
1318  // the iterator pointing to the rend (just before the beginning) of the List
1319  template < typename Val, typename Alloc >
1320  INLINE const ListIteratorSafe< Val >& List< Val, Alloc >::rendSafe() noexcept {
1321  return *(reinterpret_cast< const ListIteratorSafe< Val >* >(_list_end_safe_));
1322  }
1323 
1324  // the iterator pointing to the rend (just before the beginning) of the List
1325  template < typename Val, typename Alloc >
1326  INLINE const ListConstIterator< Val >& List< Val, Alloc >::crend() const noexcept {
1327  return *(reinterpret_cast< const ListConstIterator< Val >* >(_list_end_));
1328  }
1329 
1330  // the iterator pointing to the rend (just before the beginning) of the List
1331  template < typename Val, typename Alloc >
1332  INLINE const ListIterator< Val >& List< Val, Alloc >::rend() noexcept {
1333  return *(reinterpret_cast< const ListIterator< Val >* >(_list_end_));
1334  }
1335 
1336  // the iterator pointing to the rend (just before the beginning) of the List
1337  template < typename Val, typename Alloc >
1338  INLINE const ListConstIterator< Val >& List< Val, Alloc >::rend() const noexcept {
1339  return *(reinterpret_cast< const ListConstIterator< Val >* >(_list_end_));
1340  }
1341 
1342  // the iterator pointing to the beginning of the List
1343  template < typename Val, typename Alloc >
1345  return ListConstIteratorSafe< Val >{*this};
1346  }
1347 
1348  // the iterator pointing to the beginning of the List
1349  template < typename Val, typename Alloc >
1351  return ListIteratorSafe< Val >{*this};
1352  }
1353 
1354  // the iterator pointing to the beginning of the List
1355  template < typename Val, typename Alloc >
1357  return ListConstIterator< Val >{*this};
1358  }
1359 
1360  // the iterator pointing to the beginning of the List
1361  template < typename Val, typename Alloc >
1363  return ListIterator< Val >{*this};
1364  }
1365 
1366  // the iterator pointing to the beginning of the List
1367  template < typename Val, typename Alloc >
1369  return ListConstIterator< Val >{*this};
1370  }
1371 
1372  // the iterator pointing to the rbegin (the last element) of the List
1373  template < typename Val, typename Alloc >
1375  if (_nb_elements_)
1376  return ListConstIteratorSafe< Val >{*this, _nb_elements_ - 1};
1377  else
1378  return ListConstIteratorSafe< Val >{};
1379  }
1380 
1381  // the iterator pointing to the rbegin (the last element) of the List
1382  template < typename Val, typename Alloc >
1384  if (_nb_elements_)
1385  return ListIteratorSafe< Val >{*this, _nb_elements_ - 1};
1386  else
1387  return ListIteratorSafe< Val >{};
1388  }
1389 
1390  // the iterator pointing to the rbegin (the last element) of the List
1391  template < typename Val, typename Alloc >
1393  if (_nb_elements_)
1394  return ListConstIterator< Val >{*this, _nb_elements_ - 1};
1395  else
1396  return ListConstIterator< Val >{};
1397  }
1398 
1399  // the iterator pointing to the rbegin (the last element) of the List
1400  template < typename Val, typename Alloc >
1402  if (_nb_elements_)
1403  return ListIterator< Val >{*this, _nb_elements_ - 1};
1404  else
1405  return ListIterator< Val >{};
1406  }
1407 
1408  // the iterator pointing to the rbegin (the last element) of the List
1409  template < typename Val, typename Alloc >
1411  if (_nb_elements_)
1412  return ListConstIterator< Val >{*this, _nb_elements_ - 1};
1413  else
1414  return ListConstIterator< Val >{};
1415  }
1416 
1417  // create a new bucket with a given value
1418  template < typename Val, typename Alloc >
1420  // create a new bucket (catch allocation and construction exceptions)
1422 
1423  try {
1425  } catch (...) {
1427  throw;
1428  }
1429 
1430  return new_elt;
1431  }
1432 
1433  // create a new bucket with a given value
1434  template < typename Val, typename Alloc >
1436  // create a new bucket (catch allocation and construction exceptions)
1438 
1439  try {
1441  } catch (...) {
1443  throw;
1444  }
1445 
1446  return new_elt;
1447  }
1448 
1449  // create an emplace bucket
1450  template < typename Val, typename Alloc >
1451  template < typename... Args >
1453  // create a new bucket (catch allocation and construction exceptions)
1455 
1456  try {
1459  std::forward< Args >(args)...);
1460  } catch (...) {
1462  throw;
1463  }
1464 
1465  return new_elt;
1466  }
1467 
1468  // insert a bucket at the front of the list
1469  template < typename Val, typename Alloc >
1472 
1473  if (_deb_list_ != nullptr)
1475  else
1476  _end_list_ = new_elt;
1477 
1478  _deb_list_ = new_elt;
1479 
1480  // update the number of elements
1481  ++_nb_elements_;
1482 
1483  // return the inserted element
1484  return new_elt->_val_;
1485  }
1486 
1487  // insert a bucket at the end of the list
1488  template < typename Val, typename Alloc >
1490  // place the bucket at the end of the list
1492 
1493  if (_end_list_ != nullptr)
1495  else
1496  _deb_list_ = new_elt;
1497 
1498  _end_list_ = new_elt;
1499 
1500  // update the number of elements
1501  ++_nb_elements_;
1502 
1503  // returns the current value
1504  return new_elt->_val_;
1505  }
1506 
1507  // Insertion of a new element (a copy) at the beginning of the chained list.
1508  template < typename Val, typename Alloc >
1510  return _pushFront_(_createBucket_(val));
1511  }
1512 
1513  // Insertion of a new element (a copy) at the beginning of the chained list.
1514  template < typename Val, typename Alloc >
1516  return _pushFront_(_createBucket_(std::move(val)));
1517  }
1518 
1519  // an alias for pushFront used for STL compliance
1520  template < typename Val, typename Alloc >
1521  template < typename... Args >
1523  return pushFront(std::forward< Args >(args)...);
1524  }
1525 
1526  // emplace elements at the beginning of the chained list
1527  template < typename Val, typename Alloc >
1528  template < typename... Args >
1531  }
1532 
1533  // Insertion of a new element (a copy) at the end of the chained list.
1534  template < typename Val, typename Alloc >
1536  return _pushBack_(_createBucket_(val));
1537  }
1538 
1539  // pushBack for rvalues
1540  template < typename Val, typename Alloc >
1542  return _pushBack_(_createBucket_(std::move(val)));
1543  }
1544 
1545  // an alias for pushBack used for STL compliance
1546  template < typename Val, typename Alloc >
1547  template < typename... Args >
1549  return pushBack(std::forward< Args >(args)...);
1550  }
1551 
1552  // emplace elements at the end of the chained list
1553  template < typename Val, typename Alloc >
1554  template < typename... Args >
1557  }
1558 
1559  // Insertion of a new element at the end of the chained list (alias of
1560  // pushBack)
1561  template < typename Val, typename Alloc >
1562  INLINE Val& List< Val, Alloc >::insert(const Val& val) {
1563  return pushBack(val);
1564  }
1565 
1566  // insert for rvalues
1567  template < typename Val, typename Alloc >
1569  return pushBack(std::move(val));
1570  }
1571 
1572  // returns the bucket corresponding to the ith position
1573  template < typename Val, typename Alloc >
1574  INLINE ListBucket< Val >* List< Val, Alloc >::_getIthBucket_(Size i) const noexcept {
1575  ListBucket< Val >* ptr;
1576 
1577  if (i < _nb_elements_ / 2) {
1578  for (ptr = _deb_list_; i; --i, ptr = ptr->_next_) {}
1579  } else {
1580  for (ptr = _end_list_, i = _nb_elements_ - i - 1; i; --i, ptr = ptr->_prev_) {}
1581  }
1582 
1583  return ptr;
1584  }
1585 
1586  // insert a new bucket before another one
1587  template < typename Val, typename Alloc >
1589  ListBucket< Val >* current_elt) {
1593 
1594  if (new_elt->_prev_ == nullptr)
1595  _deb_list_ = new_elt;
1596  else
1598 
1599  // update the number of elements
1600  ++_nb_elements_;
1601 
1602  // returns the current value
1603  return new_elt->_val_;
1604  }
1605 
1606  // insert a new bucket after another one
1607  template < typename Val, typename Alloc >
1609  ListBucket< Val >* current_elt) {
1613 
1614  if (new_elt->_next_ == nullptr)
1615  _end_list_ = new_elt;
1616  else
1618 
1619  // update the number of elements
1620  ++_nb_elements_;
1621 
1622  // returns the current value
1623  return new_elt->_val_;
1624  }
1625 
1626  // inserts a new element at the ith pos of the chained list
1627  template < typename Val, typename Alloc >
1629  // if ther are fewer elements than pos, put the value at the end of the list
1630  if (_nb_elements_ <= pos) { return pushBack(val); }
1631 
1633  }
1634 
1635  // insert an rvalue at the ith pos of the chained list
1636  template < typename Val, typename Alloc >
1638  // if ther are fewer elements than pos, put the value at the end of the list
1639  if (_nb_elements_ <= pos) { return pushBack(std::move(val)); }
1640 
1642  }
1643 
1644  // inserts a new bucket before or after the location pointed to by an
1645  // iterator
1646  template < typename Val, typename Alloc >
1648  ListBucket< Val >* new_elt,
1649  location place) {
1650  // find the location around which the new element should be inserted
1651  ListBucket< Val >* ptr;
1652 
1653  if (iter._null_pointing_) {
1654  if (place == location::BEFORE) {
1656  } else {
1658  }
1659  } else {
1660  ptr = iter._getBucket_();
1661  }
1662 
1663  if (ptr == nullptr) {
1664  // here, we are at the end of the list
1665  return _pushBack_(new_elt);
1666  } else {
1667  switch (place) {
1668  case location::BEFORE:
1669  return _insertBefore_(new_elt, ptr);
1670 
1671  case location::AFTER:
1672  return _insertAfter_(new_elt, ptr);
1673 
1674  default:
1675  GUM_ERROR(FatalError, "List insertion for this location unimplemented")
1676  }
1677  }
1678  }
1679 
1680  // inserts a new bucket before or after the location pointed to by an
1681  // iterator
1682  template < typename Val, typename Alloc >
1684  ListBucket< Val >* new_elt,
1685  location place) {
1686  // find the location around which the new element should be inserted
1687  ListBucket< Val >* ptr = iter._getBucket_();
1688 
1689  if (ptr == nullptr) {
1690  // here, we are at the end of the list
1691  return _pushBack_(new_elt);
1692  } else {
1693  switch (place) {
1694  case location::BEFORE:
1695  return _insertBefore_(new_elt, ptr);
1696 
1697  case location::AFTER:
1698  return _insertAfter_(new_elt, ptr);
1699 
1700  default:
1701  GUM_ERROR(FatalError, "List insertion for this location unimplemented")
1702  }
1703  }
1704  }
1705 
1706  // inserts a new element before or after the location pointed to by an
1707  // iterator
1708  template < typename Val, typename Alloc >
1709  INLINE Val&
1711  // if the iterator does not point to the list, raise an exception
1712  if (iter._list_ != this) {
1713  GUM_ERROR(InvalidArgument, "the iterator does not point to the correct list")
1714  }
1715 
1716  return _insert_(iter, _createBucket_(val), place);
1717  }
1718 
1719  // inserts a new element before or after the location pointed to by an
1720  // iterator
1721  template < typename Val, typename Alloc >
1722  INLINE Val&
1724  // if the iterator does not point to the list, raise an exception
1725  if (iter._list_ != this) {
1726  GUM_ERROR(InvalidArgument, "the iterator does not point to the correct list")
1727  }
1728 
1729  return _insert_(iter, _createBucket_(std::move(val)), place);
1730  }
1731 
1732  // inserts a new element before or after the location pointed to by an
1733  // iterator
1734  template < typename Val, typename Alloc >
1735  INLINE Val&
1737  return _insert_(iter, _createBucket_(val), place);
1738  }
1739 
1740  // inserts a new element before or after the location pointed to by an
1741  // iterator
1742  template < typename Val, typename Alloc >
1744  return _insert_(iter, _createBucket_(std::move(val)), place);
1745  }
1746 
1747  // emplace a new element before a given iterator
1748  template < typename Val, typename Alloc >
1749  template < typename... Args >
1752  }
1753 
1754  // emplace a new element before a given iterator
1755  template < typename Val, typename Alloc >
1756  template < typename... Args >
1759  }
1760 
1761  // returns a reference to first element of a list
1762  template < typename Val, typename Alloc >
1763  INLINE Val& List< Val, Alloc >::front() const {
1764  if (_nb_elements_ == Size(0)) { GUM_ERROR(NotFound, "not enough elements in the chained list") }
1765 
1766  return _deb_list_->_val_;
1767  }
1768 
1769  // returns a reference to last element of a list
1770  template < typename Val, typename Alloc >
1771  INLINE Val& List< Val, Alloc >::back() const {
1772  if (_nb_elements_ == Size(0)) { GUM_ERROR(NotFound, "not enough elements in the chained list") }
1773 
1774  return _end_list_->_val_;
1775  }
1776 
1777  // returns the number of elements in the list.
1778  template < typename Val, typename Alloc >
1779  INLINE Size List< Val, Alloc >::size() const noexcept {
1780  return _nb_elements_;
1781  }
1782 
1783  // checks whether there exists a given element in the list.
1784  template < typename Val, typename Alloc >
1785  INLINE bool List< Val, Alloc >::exists(const Val& val) const {
1786  for (ListBucket< Val >* ptr = _deb_list_; ptr != nullptr; ptr = ptr->_next_)
1787  if (ptr->_val_ == val) return true;
1788 
1789  return false;
1790  }
1791 
1792  // suppresses a given bucket from a chained list.
1793  template < typename Val, typename Alloc >
1795  // perform deletion only if there is a bucket to remove
1796  if (bucket != nullptr) {
1797  // update the iterators pointing on this element
1798  for (const auto ptr_iter: _safe_iterators_) {
1799  if (ptr_iter->_bucket_ == bucket) {
1802  ptr_iter->_bucket_ = nullptr;
1803  ptr_iter->_null_pointing_ = true;
1804  } else {
1805  if (ptr_iter->_null_pointing_) {
1808 
1811  }
1812  }
1813  }
1814 
1815  // set properly the begin and end of the chained list (the other chainings
1816  // will be performed by operator delete)
1817  if (bucket->_prev_ == nullptr)
1819  else
1821 
1822  if (bucket->_next_ == nullptr)
1824  else
1826 
1827  // remove the current element src the list
1830 
1831  --_nb_elements_;
1832  }
1833  }
1834 
1835  // erases the ith element of the List (the first one is in position 0)
1836  template < typename Val, typename Alloc >
1837  INLINE void List< Val, Alloc >::erase(Size i) {
1838  if (i >= _nb_elements_) return;
1839 
1840  // erase the ith bucket
1842  }
1843 
1844  // erases the element of the List pointed to by the iterator
1845  template < typename Val, typename Alloc >
1848  }
1849 
1850  // erases the element of the List pointed to by the iterator
1851  template < typename Val, typename Alloc >
1854  }
1855 
1856  // returns the bucket corresponding to a given value.
1857  template < typename Val, typename Alloc >
1858  INLINE ListBucket< Val >* List< Val, Alloc >::_getBucket_(const Val& val) const noexcept {
1859  for (ListBucket< Val >* ptr = _deb_list_; ptr != nullptr; ptr = ptr->_next_)
1860  if (ptr->_val_ == val) return ptr;
1861 
1862  return nullptr;
1863  }
1864 
1865  // erases the first element encountered with a given value
1866  template < typename Val, typename Alloc >
1867  INLINE void List< Val, Alloc >::eraseByVal(const Val& val) {
1869  }
1870 
1871  // erases all the elements encountered with a given value
1872  template < typename Val, typename Alloc >
1873  INLINE void List< Val, Alloc >::eraseAllVal(const Val& val) {
1874  for (ListBucket< Val >*iter = _deb_list_, *next_bucket = nullptr; iter != nullptr;
1875  iter = next_bucket) {
1876  next_bucket = iter->_next_;
1877 
1878  if (val == iter->_val_) _erase_(iter);
1879  }
1880  }
1881 
1882  // removes the last element of a List
1883  template < typename Val, typename Alloc >
1884  INLINE void List< Val, Alloc >::popBack() {
1886  }
1887 
1888  // removes the first element of a List
1889  template < typename Val, typename Alloc >
1890  INLINE void List< Val, Alloc >::popFront() {
1892  }
1893 
1894  // returns a boolean indicating whether the chained list is empty
1895  template < typename Val, typename Alloc >
1896  INLINE bool List< Val, Alloc >::empty() const noexcept {
1897  return (_nb_elements_ == Size(0));
1898  }
1899 
1900  // displays the content of a chained list
1901  template < typename Val, typename Alloc >
1902  std::string List< Val, Alloc >::toString() const {
1903  bool deja = false;
1905  stream << "[";
1906 
1907  for (ListBucket< Val >* ptr = _deb_list_; ptr != nullptr; ptr = ptr->_next_, deja = true) {
1908  if (deja) stream << " --> ";
1909 
1910  stream << ptr->_val_;
1911  }
1912 
1913  stream << "]";
1914 
1915  return stream.str();
1916  }
1917 
1918  // creates a list of mountains src a list of val
1919  template < typename Val, typename Alloc >
1920  template < typename Mount, typename OtherAlloc >
1921  List< Mount, OtherAlloc > List< Val, Alloc >::map(Mount (*f)(Val)) const {
1922  // create a new empty list
1923  List< Mount, OtherAlloc > list;
1924 
1925  // fill the new list
1926  for (const_iterator iter = begin(); iter != end(); ++iter) {
1927  list.pushBack(f(*iter));
1928  }
1929 
1930  return list;
1931  }
1932 
1933  // creates a list of mountains src a list of val
1934  template < typename Val, typename Alloc >
1935  template < typename Mount, typename OtherAlloc >
1936  List< Mount, OtherAlloc > List< Val, Alloc >::map(Mount (*f)(Val&)) const {
1937  // create a new empty list
1938  List< Mount, OtherAlloc > list;
1939 
1940  // fill the new list
1941  for (const_iterator iter = begin(); iter != end(); ++iter) {
1942  list.pushBack(f(*iter));
1943  }
1944 
1945  return list;
1946  }
1947 
1948  // creates a list of mountains src a list of val
1949  template < typename Val, typename Alloc >
1950  template < typename Mount, typename OtherAlloc >
1951  List< Mount, OtherAlloc > List< Val, Alloc >::map(Mount (*f)(const Val&)) const {
1952  // create a new empty list
1953  List< Mount, OtherAlloc > list;
1954 
1955  // fill the new list
1956  for (const_iterator iter = begin(); iter != end(); ++iter) {
1957  list.pushBack(f(*iter));
1958  }
1959 
1960  return list;
1961  }
1962 
1963  // creates a list of mountains with a given value src a list of val
1964  template < typename Val, typename Alloc >
1965  template < typename Mount, typename OtherAlloc >
1966  List< Mount, OtherAlloc > List< Val, Alloc >::map(const Mount& mount) const {
1967  // create a new empty list
1968  List< Mount, OtherAlloc > list;
1969 
1970  // fill the new list
1971  for (Size i = Size(0); i < _nb_elements_; ++i)
1972  list.pushBack(mount);
1973 
1974  return list;
1975  }
1976 
1977  // creates and insert a new element at the end of the list (alias of
1978  // pushBack).
1979  template < typename Val, typename Alloc >
1980  INLINE Val& List< Val, Alloc >::operator+=(const Val& val) {
1981  return pushBack(val);
1982  }
1983 
1984  // creates and insert a new element at the end of the list (alias of
1985  // pushBack).
1986  template < typename Val, typename Alloc >
1988  return pushBack(std::move(val));
1989  }
1990 
1991  // checks whether two lists are identical (same elements in the same order)
1992  template < typename Val, typename Alloc >
1993  template < typename OtherAlloc >
1994  INLINE bool List< Val, Alloc >::operator==(const List< Val, OtherAlloc >& src) const {
1995  // check if the two lists have at least the same number of elements
1996  if (_nb_elements_ != src._nb_elements_) return false;
1997 
1998  // parse the two lists
1999  for (ListBucket< Val >*iter1 = _deb_list_, *iter2 = src._deb_list_; iter1 != nullptr;
2001  if (*iter1 != *iter2) return false;
2002 
2003  return true;
2004  }
2005 
2006  // checks whether two lists are different (different elements or orders)
2007  template < typename Val, typename Alloc >
2008  template < typename OtherAlloc >
2009  INLINE bool List< Val, Alloc >::operator!=(const List< Val, OtherAlloc >& src) const {
2010  return !operator==(src);
2011  }
2012 
2013  // returns the ith element in the current chained list.
2014  template < typename Val, typename Alloc >
2015  INLINE Val& List< Val, Alloc >::operator[](const Size i) {
2016  // check if we can return the element we ask for
2017  if (i >= _nb_elements_) { GUM_ERROR(NotFound, "not enough elements in the chained list") }
2018 
2019  return **_getIthBucket_(i);
2020  }
2021 
2022  // returns the ith element in the current chained list.
2023  template < typename Val, typename Alloc >
2024  INLINE const Val& List< Val, Alloc >::operator[](const Size i) const {
2025  // check if we can return the element we ask for
2026  if (i >= _nb_elements_) { GUM_ERROR(NotFound, "not enough elements in the chained list") }
2027 
2028  return **_getIthBucket_(i);
2029  }
2030 
2031  // replace the current list with another one
2032  template < typename Val, typename Alloc >
2039  }
2040 
2041  // A \c << operator for List
2042  template < typename Val >
2044  stream << list.toString();
2045  return stream;
2046  }
2047 
2048 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643