aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
list_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 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  Args&&... args) :
59  val__(std::forward< Args >(args)...) {
60  // for debugging purposes
62  }
63 
64  // copy constructor
65  template < typename Val >
67  val__{src.val__} {
68  // for debugging purposes
70  }
71 
72  // copy operator
73  template < typename Val >
76  // for debugging purposes
78 
79  // no need to avoid self assignment
80  val__ = src.val__;
81  return *this;
82  }
83 
84  // WARNING: during its deletion, the bucket does not take care of properly
85  // re-chaining the chained list. This should be done by the Lists themselves
86  template < typename Val >
88  // for debugging purposes
90  }
91 
92  // equality check
93  template < typename Val >
94  INLINE bool ListBucket< Val >::operator==(const ListBucket< Val >& src) const {
95  return (src.val__ == val__);
96  }
97 
98  // inequality check
99  template < typename Val >
100  INLINE bool ListBucket< Val >::operator!=(const ListBucket< Val >& src) const {
101  return (src.val__ != val__);
102  }
103 
104  // dereferencing operator
105  template < typename Val >
106  INLINE const Val& ListBucket< Val >::operator*() const noexcept {
107  return val__;
108  }
109 
110  // dereferencing operator
111  template < typename Val >
112  INLINE Val& ListBucket< Val >::operator*() noexcept {
113  return val__;
114  }
115 
116  // returns the bucket toward the next element
117  template < typename Val >
118  INLINE const ListBucket< Val >* ListBucket< Val >::next() const noexcept {
119  return next__;
120  }
121 
122  // returns the bucket toward the preceding element
123  template < typename Val >
124  INLINE const ListBucket< Val >* ListBucket< Val >::previous() const noexcept {
125  return prev__;
126  }
127 
128  // ===========================================================================
129  // ===========================================================================
130  // === UNSAFE_CONST_LIST_ITERATOR IMPLEMENTATION ===
131  // ===========================================================================
132  // ===========================================================================
133 
134  // default constructor
135  template < typename Val >
137  // for debugging purposes
139  }
140 
141  // default constructor
142  template < typename Val >
143  template < typename Alloc >
145  const List< Val, Alloc >& theList) noexcept :
147  // for debugging purposes
149  }
150 
151  // copy constructor
152  template < typename Val >
154  const ListConstIterator< Val >& src) noexcept :
156  // for debugging purposes
158  }
159 
160  // move constructor
161  template < typename Val >
163  ListConstIterator< Val >&& src) noexcept :
165  // for debugging purposes
167  }
168 
169  // Constructor for an iterator pointing to the \e ind_eltth element of a
170  // List.
171  template < typename Val >
173  Size ind_elt) {
174  // for debugging purposes
176 
177  // check if the index ind_elt passed as parameter is valid
178  if (ind_elt >= theList.nb_elements__) {
179  GUM_ERROR(UndefinedIteratorValue, "Not enough elements in the list");
180  }
181 
182  // check if it is faster to find the indexth element from the start or
183  // from the end of the list
184  if (ind_elt < (theList.nb_elements__ >> 1)) {
185  // find the element we shall point to src the start of the list
187  --ind_elt, bucket__ = bucket__->next__) {}
188  } else {
189  // find the element we shall point to src the end of the list
190  for (bucket__ = theList.end_list__,
192  ind_elt;
193  --ind_elt, bucket__ = bucket__->prev__) {}
194  }
195  }
196 
197  // Destructor
198  template < typename Val >
200  // for debugging purposes
202  }
203 
204  // Copy operator
205  template < typename Val >
207  const ListConstIterator< Val >& src) noexcept {
208  // for debugging purposes
210 
212  return *this;
213  }
214 
215  // move operator
216  template < typename Val >
219  // for debugging purposes
222  return *this;
223  }
224 
225  // returns the bucket the iterator is pointing to
226  template < typename Val >
227  INLINE ListBucket< Val >*
228  ListConstIterator< Val >::getBucket__() const noexcept {
229  return bucket__;
230  }
231 
232  // Makes the iterator point toward nothing
233  template < typename Val >
234  INLINE void ListConstIterator< Val >::clear() noexcept {
235  bucket__ = nullptr;
236  }
237 
238  // positions the iterator to the end of the list
239  template < typename Val >
240  INLINE void ListConstIterator< Val >::setToEnd() noexcept {
241  bucket__ = nullptr;
242  }
243 
244  // returns a bool indicating whether the iterator points to the end of the
245  // list
246  template < typename Val >
247  INLINE bool ListConstIterator< Val >::isEnd() const noexcept {
248  return (bucket__ == nullptr);
249  }
250 
251  // makes the iterator point to the next element in the List
252  template < typename Val >
254  ListConstIterator< Val >::operator++() noexcept {
255  // if we are pointing to an element of the chained list, just
256  // point on the next bucket in this list
257  if (bucket__ != nullptr) { bucket__ = bucket__->next__; }
258 
259  return *this;
260  }
261 
262  // makes the iterator point to the next element in the List
263  template < typename Val >
265  typename ListConstIterator< Val >::difference_type i) noexcept {
266  if (i >= 0) {
267  for (; i && (bucket__ != nullptr); --i, bucket__ = bucket__->next__) {}
268  } else {
269  for (; i && (bucket__ != nullptr); ++i, bucket__ = bucket__->prev__) {}
270  }
271  return *this;
272  }
273 
274  // makes the iterator point to the preceding element in the List
275  template < typename Val >
277  ListConstIterator< Val >::operator--() noexcept {
278  // if we are pointing to an element of the chained list, just
279  // point on the preceding bucket in this list
280  if (bucket__ != nullptr) { bucket__ = bucket__->prev__; }
281 
282  return *this;
283  }
284 
285  // makes the iterator point to i elements before in the list
286  template < typename Val >
288  typename ListConstIterator< Val >::difference_type i) noexcept {
289  if (i >= 0) {
290  for (; i && (bucket__ != nullptr); --i, bucket__ = bucket__->prev__) {}
291  } else {
292  for (; i && (bucket__ != nullptr); ++i, bucket__ = bucket__->next__) {}
293  }
294  return *this;
295  }
296 
297  // returns a new iterator
298  template < typename Val >
300  typename ListConstIterator< Val >::difference_type i) noexcept {
301  return ListConstIterator< Val >(*this) += i;
302  }
303 
304  // returns a new iterator
305  template < typename Val >
307  typename ListConstIterator< Val >::difference_type i) noexcept {
308  return ListConstIterator< Val >(*this) -= i;
309  }
310 
311  // checks whether two iterators point toward different elements
312  template < typename Val >
314  const ListConstIterator< Val >& src) const noexcept {
315  return (bucket__ != src.bucket__);
316  }
317 
318  // checks whether two iterators point toward the same elements.
319  template < typename Val >
321  const ListConstIterator< Val >& src) const noexcept {
322  return (bucket__ == src.bucket__);
323  }
324 
325  // dereferences the value pointed to by the iterator
326  template < typename Val >
327  INLINE const Val* ListConstIterator< Val >::operator->() const {
328  if (bucket__ != nullptr)
329  return &(bucket__->val__);
330  else {
331  GUM_ERROR(UndefinedIteratorValue, "Accessing a NULL object");
332  }
333  }
334 
335  // gives access to the content of the iterator
336  template < typename Val >
337  INLINE const Val& ListConstIterator< Val >::operator*() const {
338  if (bucket__ != nullptr)
339  return bucket__->val__;
340  else {
341  GUM_ERROR(UndefinedIteratorValue, "Accessing a NULL object");
342  }
343  }
344 
345  // for STL compliance, a distance operator
346  template < typename Val >
349  const ListConstIterator< Val >& iter2) {
350  typename ListConstIterator< Val >::difference_type res = 0;
351 
352  for (ListConstIterator< Val > iter3 = iter2; iter1 != iter3; ++iter3, ++res) {}
353 
354  return res;
355  }
356 
357  // ===========================================================================
358  // ===========================================================================
359  // === UNSAFE_LIST_ITERATOR IMPLEMENTATION ===
360  // ===========================================================================
361  // ===========================================================================
362 
363  // basic constructor
364  template < typename Val >
366  ListConstIterator< Val >() {
368  }
369 
370  // constructor for a begin
371  template < typename Val >
372  template < typename Alloc >
373  INLINE
374  ListIterator< Val >::ListIterator(const List< Val, Alloc >& theList) noexcept
375  :
378  }
379 
380  // copy constructor
381  template < typename Val >
383  :
386  }
387 
388  // move constructor
389  template < typename Val >
393  }
394 
395  // Constructor for an iterator pointing to the \e ind_eltth element of a
396  // List.
397  template < typename Val >
399  Size ind_elt) :
402  }
403 
404  // Copy operator
405  template < typename Val >
407  ListIterator< Val >::operator=(const ListIterator< Val >& src) noexcept {
410  return *this;
411  }
412 
413  // move operator
414  template < typename Val >
416  ListIterator< Val >::operator=(ListIterator< Val >&& src) noexcept {
419  return *this;
420  }
421 
422  // Destructor
423  template < typename Val >
426  }
427 
428  // makes the iterator point to the next element in the List
429  template < typename Val >
432  return *this;
433  }
434 
435  // makes the iterator point to i elements further in the List
436  template < typename Val >
438  typename ListIterator< Val >::difference_type i) noexcept {
440  return *this;
441  }
442 
443  // makes the iterator point to the preceding element in the List
444  template < typename Val >
447  return *this;
448  }
449 
450  // makes the iterator point to i elements before in the List
451  template < typename Val >
453  typename ListIterator< Val >::difference_type i) noexcept {
455  return *this;
456  }
457 
458  // returns a new iterator
459  template < typename Val >
461  typename ListIterator< Val >::difference_type i) noexcept {
462  return ListIterator< Val >(*this) += i;
463  }
464 
465  // returns a new iterator
466  template < typename Val >
468  typename ListIterator< Val >::difference_type i) noexcept {
469  return ListIterator< Val >(*this) -= i;
470  }
471 
472  // dereferences the value pointed to by the iterator
473  template < typename Val >
475  return const_cast< Val* >(ListConstIterator< Val >::operator->());
476  }
477 
478  // gives access to the content of the iterator
479  template < typename Val >
481  return const_cast< Val& >(ListConstIterator< Val >::operator*());
482  }
483 
484  // ===========================================================================
485  // ===========================================================================
486  // === SAFE LIST CONST ITERATOR IMPLEMENTATION ===
487  // ===========================================================================
488  // ===========================================================================
489 
490  // basic constructor
491  template < typename Val >
493  // for debugging purposes
495  }
496 
497  // Constructor for a begin
498  template < typename Val >
499  template < typename Alloc >
501  const List< Val, Alloc >& theList) :
502  list__{
503  reinterpret_cast< const List< Val, std::allocator< Val > >* >(&theList)},
505  // for debugging purposes
507 
508  // add the iterator to the list of safe iterators
510  }
511 
512  // copy constructor
513  template < typename Val >
515  const ListConstIteratorSafe< Val >& src) :
516  list__{src.list__},
520  // for debugging purposes
522 
523  // add the iterator to the list of safe iterators
524  if (list__ != nullptr) list__->safe_iterators__.push_back(this);
525  }
526 
527  // Constructor for an iterator pointing to the \e ind_eltth element of a
528  // List.
529  template < typename Val >
530  template < typename Alloc >
532  const List< Val, Alloc >& theList,
533  Size ind_elt) :
534  list__{
535  reinterpret_cast< const List< Val, std::allocator< Val > >* >(&theList)} {
536  // for debugging purposes
538 
539  // check if the index ind_elt passed as parameter is valid
540  if (ind_elt >= list__->nb_elements__) {
541  GUM_ERROR(UndefinedIteratorValue, "Not enough elements in the list");
542  }
543 
544  // check if it is faster to find the indexth element src the start or
545  // src the end of the list
546  if (ind_elt < (list__->nb_elements__ >> 1)) {
547  // find the element we shall point to src the start of the list
549  --ind_elt, bucket__ = bucket__->next__) {}
550  } else {
551  // find the element we shall point to src the end of the list
552  for (bucket__ = list__->end_list__,
554  ind_elt;
555  --ind_elt, bucket__ = bucket__->prev__) {}
556  }
557 
558  // add the iterator to the list of safe iterators
560  }
561 
562  // move constructor
563  template < typename Val >
566  list__{src.list__},
570  // for debugging purposes
572 
573  if (list__ != nullptr) {
574  // substitute src by this in the list of safe iterators
577 
578  for (auto ptr = vect.rbegin(); ptr != vect.rend(); --ptr) {
579  if (*ptr == &src) {
580  *ptr = this;
581  break;
582  }
583  }
584 
585  src.list__ = nullptr;
586  src.bucket__ = nullptr;
587  src.null_pointing__ = false;
588  }
589  }
590 
591  // remove the iterator for its list' safe iterators list
592  template < typename Val >
594  // find where the iterator is
596 
597  for (auto i = vect.size() - 1; i >= 0; --i) {
598  if (vect[i] == this) {
599  vect.erase(vect.begin() + i);
600  break;
601  }
602  }
603  }
604 
605  // Copy operator
606  template < typename Val >
608  const ListConstIteratorSafe< Val >& src) {
609  // avoid self assignment
610  if (this != &src) {
611  // for debugging purposes
613 
614  // check if src and this belong to the same list. If this is not
615  // the case, we shall remove this from its iterator's list and
616  // put it into src's list one.
617  if (list__ && (src.list__ != list__)) {
619  list__ = nullptr;
620  }
621 
622  // if necessary, put this into the same list of safe iterators as src
623  if (src.list__ && (src.list__ != list__)) {
624  try {
626  } catch (...) {
627  list__ = nullptr;
628  bucket__ = nullptr;
629  null_pointing__ = false;
630  throw;
631  }
632  }
633 
634  list__ = src.list__;
639  }
640 
641  return *this;
642  }
643 
644  // move operator
645  template < typename Val >
648  // avoid self assignment
649  if (this != &src) {
650  // for debugging purposes
652 
653  // if the two iterators do not point to the same list, remove
654  // the current iterator from its safe iterators list
655  if ((list__ != nullptr) && (src.list__ != list__)) {
657  list__ = nullptr;
658  }
659 
660  // now if src points to a list, put this at its location
661  if ((src.list__ != nullptr)) {
664  Idx index_src = Size(vect.size()) - 1;
665 
666  for (;; --index_src) {
667  if (vect[index_src] == &src) { break; }
668  }
669 
670  if (list__ == nullptr) {
671  vect[index_src] = this;
672  } else {
674  }
675  }
676 
677  list__ = src.list__;
682 
683  src.list__ = nullptr;
684  src.bucket__ = nullptr;
685  src.null_pointing__ = false;
686  }
687 
688  return *this;
689  }
690 
691  // Destructor
692  template < typename Val >
694  // for debugging purposes
696 
697  // remove the iterator src the table's iterator list
699  }
700 
701  // returns the bucket the iterator is pointing to
702  template < typename Val >
703  INLINE ListBucket< Val >*
704  ListConstIteratorSafe< Val >::getBucket__() const noexcept {
705  return bucket__;
706  }
707 
708  // Makes the iterator point toward nothing
709  template < typename Val >
711  // remove the iterator src the list's iterator list
713 
714  // set its list as well as the element it points to to nullptr
715  list__ = nullptr;
716  bucket__ = nullptr;
717  null_pointing__ = false;
718  }
719 
720  // positions the iterator to the end of the list
721  template < typename Val >
723  clear();
724  }
725 
726  // returns a bool indicating whether the iterator points to the end of the
727  // list
728  template < typename Val >
730  return null_pointing__ ? (next_current_bucket__ == nullptr)
731  && (prev_current_bucket__ == nullptr)
732  : (bucket__ == nullptr);
733  }
734 
735  // makes the iterator point to the next element in the List
736  template < typename Val >
738  ListConstIteratorSafe< Val >::operator++() noexcept {
739  // check if we are pointing to something that has been deleted
740  if (null_pointing__) {
741  null_pointing__ = false;
742 
743  // if we are pointing to an element of the chained list that has been
744  // deleted
745  // but that has a next element, just point on the latter
746  if (next_current_bucket__ != nullptr) {
748  return *this;
749  }
750 
751  // here we were pointing on an extremity of the list (either end or rend)
752  // if prev_current_bucket is not null, then we are at rend and doing
753  // a ++ shall now point to the beginning of the list
754  if (prev_current_bucket__ != nullptr) {
756  return *this;
757  }
758 
759  // here, we are at the end of the chained list, hence we shall remain at
760  // end
761  bucket__ = nullptr;
762  return *this;
763  } else {
764  // if we are pointing to an element of the chained list, just
765  // point on the next bucket in this list
766  if (bucket__ != nullptr) { bucket__ = bucket__->next__; }
767 
768  return *this;
769  }
770  }
771 
772  // makes the iterator point to i elements before in the List
773  template < typename Val >
776  // check if we are pointing to something that has been deleted
777  if (null_pointing__) {
778  null_pointing__ = false;
779 
780  // if we are pointing to an element of the chained list that has been
781  // deleted
782  // but that has a preceding element, just point on the latter
783  if (prev_current_bucket__ != nullptr) {
785  } else {
786  // here we were pointing on an extremity of the list (either end or
787  // rend)
788  // if next_current_bucket is not null, then we are at end and doing
789  // a -- shall now point to the beginning of the list
790  if (next_current_bucket__ != nullptr) {
792  } else {
793  // here, we are at the rend of the chained list, hence we shall remain
794  // at rend
795  bucket__ = nullptr;
796  return *this;
797  }
798  }
799  } else {
800  // if we are pointing to an element of the chained list, just
801  // point on the preceding bucket in this list
802  if (bucket__ != nullptr) { bucket__ = bucket__->prev__; }
803  }
804 
805  for (--i; i && (bucket__ != nullptr); --i, bucket__ = bucket__->prev__) {}
806 
807  return *this;
808  }
809 
810  // makes the iterator point to the next element in the List
811  template < typename Val >
814  // check if we are pointing to something that has been deleted
815  if (null_pointing__) {
816  null_pointing__ = false;
817 
818  // if we are pointing to an element of the chained list that has been
819  // deleted
820  // but that has a next element, just point on the latter
821  if (next_current_bucket__ != nullptr) {
823  } else {
824  // here we were pointing on an extremity of the list (either end or
825  // rend)
826  // if prev_current_bucket is not null, then we are at rend and doing
827  // a ++ shall now point to the beginning of the list
828  if (prev_current_bucket__ != nullptr) {
830  } else {
831  // here, we are at the end of the chained list, hence we shall
832  // remain at end
833  bucket__ = nullptr;
834  return *this;
835  }
836  }
837  } else {
838  // if we are pointing to an element of the chained list, just
839  // point on the next bucket in this list
840  if (bucket__ != nullptr) { bucket__ = bucket__->next__; }
841  }
842 
843  for (--i; i && (bucket__ != nullptr); --i, bucket__ = bucket__->next__) {}
844 
845  return *this;
846  }
847 
848  // makes the iterator point to the next element in the List
849  template < typename Val >
851  typename ListConstIteratorSafe< Val >::difference_type i) noexcept {
852  if (!i) return *this;
853 
854  if (i < 0)
855  return opMinus__(-i);
856  else
857  return opPlus__(i);
858  }
859 
860  // makes the iterator point to the preceding element in the List
861  template < typename Val >
863  ListConstIteratorSafe< Val >::operator--() noexcept {
864  // check if we are pointing to something that has been deleted
865  if (null_pointing__) {
866  null_pointing__ = false;
867 
868  // if we are pointing to an element of the chained list that has been
869  // deleted
870  // but that has a preceding element, just point on the latter
871  if (prev_current_bucket__ != nullptr) {
873  return *this;
874  }
875 
876  // here we were pointing on an extremity of the list (either end or rend)
877  // if next_current_bucket is not null, then we are at end and doing
878  // a -- shall now point to the beginning of the list
879  if (next_current_bucket__ != nullptr) {
881  return *this;
882  }
883 
884  // here, we are at the rend of the chained list, hence we shall remain
885  // at rend
886  bucket__ = nullptr;
887  return *this;
888  } else {
889  // if we are pointing to an element of the chained list, just
890  // point on the preceding bucket in this list
891  if (bucket__ != nullptr) { bucket__ = bucket__->prev__; }
892 
893  return *this;
894  }
895  }
896 
897  // makes the iterator point to i elements before in the List
898  template < typename Val >
900  typename ListConstIteratorSafe< Val >::difference_type i) noexcept {
901  if (!i) return *this;
902 
903  if (i < 0)
904  return opPlus__(-i);
905  else
906  return opMinus__(i);
907  }
908 
909  // returns a new iterator
910  template < typename Val >
912  typename ListConstIteratorSafe< Val >::difference_type i) noexcept {
913  return ListConstIteratorSafe< Val >(*this) += i;
914  }
915 
916  // returns a new iterator
917  template < typename Val >
919  typename ListConstIteratorSafe< Val >::difference_type i) noexcept {
920  return ListConstIteratorSafe< Val >(*this) -= i;
921  }
922 
923  // checks whether two iterators point toward different elements
924  template < typename Val >
926  const ListConstIteratorSafe< Val >& src) const {
927  return null_pointing__
930  : (bucket__ != src.bucket__);
931  }
932 
933  // checks whether two iterators point toward the same elements.
934  template < typename Val >
936  const ListConstIteratorSafe< Val >& src) const {
937  return null_pointing__
940  : (bucket__ == src.bucket__);
941  }
942 
943  // dereferences the value pointed to by the iterator
944  template < typename Val >
945  INLINE const Val* ListConstIteratorSafe< Val >::operator->() const {
946  if (bucket__ != nullptr)
947  return &(bucket__->val__);
948  else {
949  GUM_ERROR(UndefinedIteratorValue, "Accessing a NULL object");
950  }
951  }
952 
953  // gives access to the content of the iterator
954  template < typename Val >
956  if (bucket__ != nullptr)
957  return bucket__->val__;
958  else {
959  GUM_ERROR(UndefinedIteratorValue, "Accessing a NULL object");
960  }
961  }
962 
963  // for STL compliance, a distance operator
964  template < typename Val >
967  const ListConstIteratorSafe< Val >& iter2) {
968  typename ListConstIteratorSafe< Val >::difference_type res = 0;
970 
971  for (; iter1 != iter3; ++iter3, ++res) {}
972 
973  return res;
974  }
975 
976  // ===========================================================================
977  // ===========================================================================
978  // === LIST ITERATOR IMPLEMENTATION ===
979  // ===========================================================================
980  // ===========================================================================
981 
982  // basic constructor
983  template < typename Val >
987  }
988 
989  // constructor for a begin
990  template < typename Val >
991  template < typename Alloc >
992  INLINE
996  }
997 
998  // copy constructor
999  template < typename Val >
1001  const ListIteratorSafe< Val >& src) :
1004  }
1005 
1006  // Constructor for an iterator pointing to the \e ind_eltth element of a
1007  // List.
1008  template < typename Val >
1009  template < typename Alloc >
1010  INLINE
1012  Size ind_elt) :
1015  }
1016 
1017  // move constructor
1018  template < typename Val >
1022  }
1023 
1024  // Copy operator
1025  template < typename Val >
1028  // for debugging purposes
1031  return *this;
1032  }
1033 
1034  // move operator
1035  template < typename Val >
1038  // for debugging purposes
1041  return *this;
1042  }
1043 
1044  // Destructor
1045  template < typename Val >
1048  }
1049 
1050  // makes the iterator point to the next element in the List
1051  template < typename Val >
1054  return *this;
1055  }
1056 
1057  // makes the iterator point to the next element in the List
1058  template < typename Val >
1060  typename ListIteratorSafe< Val >::difference_type i) noexcept {
1062  return *this;
1063  }
1064 
1065  // makes the iterator point to the preceding element in the List
1066  template < typename Val >
1069  return *this;
1070  }
1071 
1072  // makes the iterator point to the preceding element in the List
1073  template < typename Val >
1075  typename ListIteratorSafe< Val >::difference_type i) noexcept {
1077  return *this;
1078  }
1079 
1080  // returns a new iterator
1081  template < typename Val >
1083  typename ListIteratorSafe< Val >::difference_type i) noexcept {
1084  return ListIteratorSafe< Val >(*this) += i;
1085  }
1086 
1087  // returns a new iterator
1088  template < typename Val >
1090  typename ListIteratorSafe< Val >::difference_type i) noexcept {
1091  return ListIteratorSafe< Val >(*this) -= i;
1092  }
1093 
1094  // dereferences the value pointed to by the iterator
1095  template < typename Val >
1097  return const_cast< Val* >(ListConstIteratorSafe< Val >::operator->());
1098  }
1099 
1100  // gives access to the content of the iterator
1101  template < typename Val >
1103  return const_cast< Val& >(ListConstIteratorSafe< Val >::operator*());
1104  }
1105 
1106  // ===========================================================================
1107  // ===========================================================================
1108  // === LIST IMPLEMENTATION ===
1109  // ===========================================================================
1110  // ===========================================================================
1111 
1112  // a function used to perform copies of elements of Lists
1113  template < typename Val, typename Alloc >
1114  template < typename OtherAlloc >
1116  ListBucket< Val >* ptr;
1117  ListBucket< Val >* old_ptr = nullptr;
1118  ListBucket< Val >* new_elt = nullptr;
1119 
1120  // copy src's list
1121  try {
1122  for (ptr = src.deb_list__; ptr != nullptr; ptr = ptr->next__) {
1123  // create a copy bucket
1125 
1126  try {
1128  } catch (...) {
1130  throw;
1131  }
1132 
1133  // rechain properly the new list (the next field is already initialized
1134  // with nullptr)
1135  new_elt->prev__ = old_ptr;
1136 
1137  if (old_ptr)
1138  old_ptr->next__ = new_elt;
1139  else
1140  deb_list__ = new_elt;
1141 
1142  old_ptr = new_elt;
1143  }
1144  } catch (...) {
1145  // problem: we could not allocate an element in the list => we delete
1146  // the elements created so far and we throw an exception
1147  for (; deb_list__ != nullptr;
1148  deb_list__ = const_cast< ListBucket< Val >* >(ptr)) {
1149  ptr = deb_list__->next__;
1152  }
1153 
1154  deb_list__ = nullptr;
1155  throw;
1156  }
1157 
1158  // update properly the end of the chained list and the number of elements
1159  end_list__ = old_ptr;
1161  }
1162 
1163  // deletes all the elements of a chained list.
1164  template < typename Val, typename Alloc >
1165  void List< Val, Alloc >::clear() {
1166  // first we update all the safe iterators of the list : they should now
1167  // point to end/rend
1168  for (const auto ptr_iter: safe_iterators__) {
1169  ptr_iter->clear();
1170  }
1171 
1172  // clear all the values
1173  for (ListBucket< Val >*ptr = deb_list__, *next_ptr = nullptr; ptr != nullptr;
1174  ptr = next_ptr) {
1175  next_ptr = ptr->next__;
1178  }
1179 
1180  nb_elements__ = 0;
1181  deb_list__ = nullptr;
1182  end_list__ = nullptr;
1183  }
1184 
1185  // A basic constructor that creates an empty list
1186  template < typename Val, typename Alloc >
1188  // for debugging purposes
1190 
1191  // reserve space for only the default number of iterators
1193  }
1194 
1195  // Copy constructor
1196  template < typename Val, typename Alloc >
1197  INLINE List< Val, Alloc >::List(const List< Val, Alloc >& src) {
1198  // for debugging purposes
1199  GUM_CONS_CPY(List);
1200 
1201  // copy the elements
1203 
1204  // reserve space for only the default number of iterators
1206  }
1207 
1208  // generalized copy constructor
1209  template < typename Val, typename Alloc >
1210  template < typename OtherAlloc >
1212  // for debugging purposes
1213  GUM_CONS_CPY(List);
1214 
1215  // copy the elements
1217 
1218  // reserve space for only the default number of iterators
1220  }
1221 
1222  // move constructor
1223  template < typename Val, typename Alloc >
1228  src.alloc_bucket__)} {
1229  // for debugging purposes
1230  GUM_CONS_MOV(List);
1231 
1232  src.deb_list__ = nullptr;
1233  src.end_list__ = nullptr;
1234  src.nb_elements__ = 0;
1236  }
1237 
1238  // initializer_list constructor
1239  template < typename Val, typename Alloc >
1241  // for debugging purposes
1243 
1244  // adding all the elements
1245  for (const auto& val: list) {
1246  pushBack(val);
1247  }
1248 
1249  // reserve space for only the default number of iterators
1251  }
1252 
1253  // Destructor
1254  template < typename Val, typename Alloc >
1256  // for debugging (although this program is bug-free)
1258 
1259  // we detach all the safe iterators attached to the current List and we
1260  // remove all the elements from the list
1261  clear();
1262  }
1263 
1264  // Copy operator. The List iterator's list is not shared with that of \e src.
1265  template < typename Val, typename Alloc >
1266  INLINE List< Val, Alloc >&
1267  List< Val, Alloc >::operator=(const List< Val, Alloc >& src) {
1268  // avoid self assignment
1269  if (this != &src) {
1270  // for debugging purposes
1271  GUM_OP_CPY(List);
1272 
1273  // remove the old content of 'this' and update accordingly the iterators
1274  clear();
1275 
1276  // perform the copy
1278  }
1279 
1280  return *this;
1281  }
1282 
1283  // Generalized copy operator.
1284  template < typename Val, typename Alloc >
1285  template < typename OtherAlloc >
1286  INLINE List< Val, Alloc >&
1287  List< Val, Alloc >::operator=(const List< Val, OtherAlloc >& src) {
1288  // avoid self assignment
1289  if (this != reinterpret_cast< List< Val, Alloc >* >(&src)) {
1290  // for debugging purposes
1291  GUM_OP_CPY(List);
1292 
1293  // remove the old content of 'this' and update accordingly the iterators
1294  clear();
1295 
1296  // perform the copy
1298  }
1299 
1300  return *this;
1301  }
1302 
1303  // move operator
1304  template < typename Val, typename Alloc >
1305  INLINE List< Val, Alloc >&
1307  // avoid self assignment
1308  if (this != &src) {
1309  // for debugging purposes
1310  GUM_OP_MOV(List);
1311 
1312  // remove the old content of 'this' and update accordingly the iterators
1313  clear();
1314 
1315  // perform the move
1321 
1322  src.deb_list__ = nullptr;
1323  src.end_list__ = nullptr;
1324  src.nb_elements__ = 0;
1326  }
1327 
1328  return *this;
1329  }
1330 
1331  // the iterator pointing to the end of the List
1332  template < typename Val, typename Alloc >
1333  INLINE const ListConstIteratorSafe< Val >&
1334  List< Val, Alloc >::cendSafe() const noexcept {
1335  return *(
1336  reinterpret_cast< const ListConstIteratorSafe< Val >* >(list_end_safe__));
1337  }
1338 
1339  // the iterator pointing to the end of the List
1340  template < typename Val, typename Alloc >
1341  INLINE const ListIteratorSafe< Val >& List< Val, Alloc >::endSafe() noexcept {
1342  return *(reinterpret_cast< const ListIteratorSafe< Val >* >(list_end_safe__));
1343  }
1344 
1345  // the iterator pointing to the end of the List
1346  template < typename Val, typename Alloc >
1347  INLINE const ListConstIterator< Val >&
1348  List< Val, Alloc >::cend() const noexcept {
1349  return *(reinterpret_cast< const ListConstIterator< Val >* >(list_end__));
1350  }
1351 
1352  // the iterator pointing to the end of the List
1353  template < typename Val, typename Alloc >
1354  INLINE const ListIterator< Val >& List< Val, Alloc >::end() noexcept {
1355  return *(reinterpret_cast< const ListIterator< Val >* >(list_end__));
1356  }
1357 
1358  // the iterator pointing to the end of the List
1359  template < typename Val, typename Alloc >
1360  INLINE const ListConstIterator< Val >& List< Val, Alloc >::end() const noexcept {
1361  return *(reinterpret_cast< const ListConstIterator< Val >* >(list_end__));
1362  }
1363 
1364  // the iterator pointing to the rend (just before the beginning) of the List
1365  template < typename Val, typename Alloc >
1366  INLINE const ListConstIteratorSafe< Val >&
1367  List< Val, Alloc >::crendSafe() const noexcept {
1368  return *(
1369  reinterpret_cast< const ListConstIteratorSafe< Val >* >(list_end_safe__));
1370  }
1371 
1372  // the iterator pointing to the rend (just before the beginning) of the List
1373  template < typename Val, typename Alloc >
1374  INLINE const ListIteratorSafe< Val >& List< Val, Alloc >::rendSafe() noexcept {
1375  return *(reinterpret_cast< const ListIteratorSafe< Val >* >(list_end_safe__));
1376  }
1377 
1378  // the iterator pointing to the rend (just before the beginning) of the List
1379  template < typename Val, typename Alloc >
1380  INLINE const ListConstIterator< Val >&
1381  List< Val, Alloc >::crend() const noexcept {
1382  return *(reinterpret_cast< const ListConstIterator< Val >* >(list_end__));
1383  }
1384 
1385  // the iterator pointing to the rend (just before the beginning) of the List
1386  template < typename Val, typename Alloc >
1387  INLINE const ListIterator< Val >& List< Val, Alloc >::rend() noexcept {
1388  return *(reinterpret_cast< const ListIterator< Val >* >(list_end__));
1389  }
1390 
1391  // the iterator pointing to the rend (just before the beginning) of the List
1392  template < typename Val, typename Alloc >
1393  INLINE const ListConstIterator< Val >&
1394  List< Val, Alloc >::rend() const noexcept {
1395  return *(reinterpret_cast< const ListConstIterator< Val >* >(list_end__));
1396  }
1397 
1398  // the iterator pointing to the beginning of the List
1399  template < typename Val, typename Alloc >
1401  return ListConstIteratorSafe< Val >{*this};
1402  }
1403 
1404  // the iterator pointing to the beginning of the List
1405  template < typename Val, typename Alloc >
1407  return ListIteratorSafe< Val >{*this};
1408  }
1409 
1410  // the iterator pointing to the beginning of the List
1411  template < typename Val, typename Alloc >
1413  return ListConstIterator< Val >{*this};
1414  }
1415 
1416  // the iterator pointing to the beginning of the List
1417  template < typename Val, typename Alloc >
1419  return ListIterator< Val >{*this};
1420  }
1421 
1422  // the iterator pointing to the beginning of the List
1423  template < typename Val, typename Alloc >
1425  return ListConstIterator< Val >{*this};
1426  }
1427 
1428  // the iterator pointing to the rbegin (the last element) of the List
1429  template < typename Val, typename Alloc >
1431  if (nb_elements__)
1432  return ListConstIteratorSafe< Val >{*this, nb_elements__ - 1};
1433  else
1434  return ListConstIteratorSafe< Val >{};
1435  }
1436 
1437  // the iterator pointing to the rbegin (the last element) of the List
1438  template < typename Val, typename Alloc >
1440  if (nb_elements__)
1441  return ListIteratorSafe< Val >{*this, nb_elements__ - 1};
1442  else
1443  return ListIteratorSafe< Val >{};
1444  }
1445 
1446  // the iterator pointing to the rbegin (the last element) of the List
1447  template < typename Val, typename Alloc >
1449  if (nb_elements__)
1450  return ListConstIterator< Val >{*this, nb_elements__ - 1};
1451  else
1452  return ListConstIterator< Val >{};
1453  }
1454 
1455  // the iterator pointing to the rbegin (the last element) of the List
1456  template < typename Val, typename Alloc >
1458  if (nb_elements__)
1459  return ListIterator< Val >{*this, nb_elements__ - 1};
1460  else
1461  return ListIterator< Val >{};
1462  }
1463 
1464  // the iterator pointing to the rbegin (the last element) of the List
1465  template < typename Val, typename Alloc >
1467  if (nb_elements__)
1468  return ListConstIterator< Val >{*this, nb_elements__ - 1};
1469  else
1470  return ListConstIterator< Val >{};
1471  }
1472 
1473  // create a new bucket with a given value
1474  template < typename Val, typename Alloc >
1475  INLINE ListBucket< Val >*
1476  List< Val, Alloc >::createBucket__(const Val& val) const {
1477  // create a new bucket (catch allocation and construction exceptions)
1479 
1480  try {
1482  } catch (...) {
1484  throw;
1485  }
1486 
1487  return new_elt;
1488  }
1489 
1490  // create a new bucket with a given value
1491  template < typename Val, typename Alloc >
1493  // create a new bucket (catch allocation and construction exceptions)
1495 
1496  try {
1498  } catch (...) {
1500  throw;
1501  }
1502 
1503  return new_elt;
1504  }
1505 
1506  // create an emplace bucket
1507  template < typename Val, typename Alloc >
1508  template < typename... Args >
1509  INLINE ListBucket< Val >*
1511  // create a new bucket (catch allocation and construction exceptions)
1513 
1514  try {
1517  std::forward< Args >(args)...);
1518  } catch (...) {
1520  throw;
1521  }
1522 
1523  return new_elt;
1524  }
1525 
1526  // insert a bucket at the front of the list
1527  template < typename Val, typename Alloc >
1530 
1531  if (deb_list__ != nullptr)
1533  else
1534  end_list__ = new_elt;
1535 
1536  deb_list__ = new_elt;
1537 
1538  // update the number of elements
1539  ++nb_elements__;
1540 
1541  // return the inserted element
1542  return new_elt->val__;
1543  }
1544 
1545  // insert a bucket at the end of the list
1546  template < typename Val, typename Alloc >
1548  // place the bucket at the end of the list
1550 
1551  if (end_list__ != nullptr)
1553  else
1554  deb_list__ = new_elt;
1555 
1556  end_list__ = new_elt;
1557 
1558  // update the number of elements
1559  ++nb_elements__;
1560 
1561  // returns the current value
1562  return new_elt->val__;
1563  }
1564 
1565  // Insertion of a new element (a copy) at the beginning of the chained list.
1566  template < typename Val, typename Alloc >
1568  return pushFront__(createBucket__(val));
1569  }
1570 
1571  // Insertion of a new element (a copy) at the beginning of the chained list.
1572  template < typename Val, typename Alloc >
1574  return pushFront__(createBucket__(std::move(val)));
1575  }
1576 
1577  // an alias for pushFront used for STL compliance
1578  template < typename Val, typename Alloc >
1579  template < typename... Args >
1581  return pushFront(std::forward< Args >(args)...);
1582  }
1583 
1584  // emplace elements at the beginning of the chained list
1585  template < typename Val, typename Alloc >
1586  template < typename... Args >
1589  }
1590 
1591  // Insertion of a new element (a copy) at the end of the chained list.
1592  template < typename Val, typename Alloc >
1594  return pushBack__(createBucket__(val));
1595  }
1596 
1597  // pushBack for rvalues
1598  template < typename Val, typename Alloc >
1600  return pushBack__(createBucket__(std::move(val)));
1601  }
1602 
1603  // an alias for pushBack used for STL compliance
1604  template < typename Val, typename Alloc >
1605  template < typename... Args >
1607  return pushBack(std::forward< Args >(args)...);
1608  }
1609 
1610  // emplace elements at the end of the chained list
1611  template < typename Val, typename Alloc >
1612  template < typename... Args >
1615  }
1616 
1617  // Insertion of a new element at the end of the chained list (alias of
1618  // pushBack)
1619  template < typename Val, typename Alloc >
1620  INLINE Val& List< Val, Alloc >::insert(const Val& val) {
1621  return pushBack(val);
1622  }
1623 
1624  // insert for rvalues
1625  template < typename Val, typename Alloc >
1627  return pushBack(std::move(val));
1628  }
1629 
1630  // returns the bucket corresponding to the ith position
1631  template < typename Val, typename Alloc >
1632  INLINE ListBucket< Val >*
1633  List< Val, Alloc >::getIthBucket__(Size i) const noexcept {
1634  ListBucket< Val >* ptr;
1635 
1636  if (i < nb_elements__ / 2) {
1637  for (ptr = deb_list__; i; --i, ptr = ptr->next__) {}
1638  } else {
1639  for (ptr = end_list__, i = nb_elements__ - i - 1; i;
1640  --i, ptr = ptr->prev__) {}
1641  }
1642 
1643  return ptr;
1644  }
1645 
1646  // insert a new bucket before another one
1647  template < typename Val, typename Alloc >
1649  ListBucket< Val >* current_elt) {
1653 
1654  if (new_elt->prev__ == nullptr)
1655  deb_list__ = new_elt;
1656  else
1658 
1659  // update the number of elements
1660  ++nb_elements__;
1661 
1662  // returns the current value
1663  return new_elt->val__;
1664  }
1665 
1666  // insert a new bucket after another one
1667  template < typename Val, typename Alloc >
1669  ListBucket< Val >* current_elt) {
1673 
1674  if (new_elt->next__ == nullptr)
1675  end_list__ = new_elt;
1676  else
1678 
1679  // update the number of elements
1680  ++nb_elements__;
1681 
1682  // returns the current value
1683  return new_elt->val__;
1684  }
1685 
1686  // inserts a new element at the ith pos of the chained list
1687  template < typename Val, typename Alloc >
1689  // if ther are fewer elements than pos, put the value at the end of the list
1690  if (nb_elements__ <= pos) { return pushBack(val); }
1691 
1693  }
1694 
1695  // insert an rvalue at the ith pos of the chained list
1696  template < typename Val, typename Alloc >
1698  // if ther are fewer elements than pos, put the value at the end of the list
1699  if (nb_elements__ <= pos) { return pushBack(std::move(val)); }
1700 
1702  }
1703 
1704  // inserts a new bucket before or after the location pointed to by an
1705  // iterator
1706  template < typename Val, typename Alloc >
1708  ListBucket< Val >* new_elt,
1709  location place) {
1710  // find the location around which the new element should be inserted
1711  ListBucket< Val >* ptr;
1712 
1713  if (iter.null_pointing__) {
1714  if (place == location::BEFORE) {
1716  } else {
1718  }
1719  } else {
1720  ptr = iter.getBucket__();
1721  }
1722 
1723  if (ptr == nullptr) {
1724  // here, we are at the end of the list
1725  return pushBack__(new_elt);
1726  } else {
1727  switch (place) {
1728  case location::BEFORE:
1729  return insertBefore__(new_elt, ptr);
1730 
1731  case location::AFTER:
1732  return insertAfter__(new_elt, ptr);
1733 
1734  default:
1735  GUM_ERROR(FatalError, "List insertion for this location unimplemented");
1736  }
1737  }
1738  }
1739 
1740  // inserts a new bucket before or after the location pointed to by an
1741  // iterator
1742  template < typename Val, typename Alloc >
1744  ListBucket< Val >* new_elt,
1745  location place) {
1746  // find the location around which the new element should be inserted
1747  ListBucket< Val >* ptr = iter.getBucket__();
1748 
1749  if (ptr == nullptr) {
1750  // here, we are at the end of the list
1751  return pushBack__(new_elt);
1752  } else {
1753  switch (place) {
1754  case location::BEFORE:
1755  return insertBefore__(new_elt, ptr);
1756 
1757  case location::AFTER:
1758  return insertAfter__(new_elt, ptr);
1759 
1760  default:
1761  GUM_ERROR(FatalError, "List insertion for this location unimplemented");
1762  }
1763  }
1764  }
1765 
1766  // inserts a new element before or after the location pointed to by an
1767  // iterator
1768  template < typename Val, typename Alloc >
1770  const Val& val,
1771  location place) {
1772  // if the iterator does not point to the list, raise an exception
1773  if (iter.list__ != this) {
1775  "the iterator does not point to the correct list");
1776  }
1777 
1778  return insert__(iter, createBucket__(val), place);
1779  }
1780 
1781  // inserts a new element before or after the location pointed to by an
1782  // iterator
1783  template < typename Val, typename Alloc >
1785  Val&& val,
1786  location place) {
1787  // if the iterator does not point to the list, raise an exception
1788  if (iter.list__ != this) {
1790  "the iterator does not point to the correct list");
1791  }
1792 
1793  return insert__(iter, createBucket__(std::move(val)), place);
1794  }
1795 
1796  // inserts a new element before or after the location pointed to by an
1797  // iterator
1798  template < typename Val, typename Alloc >
1800  const Val& val,
1801  location place) {
1802  return insert__(iter, createBucket__(val), place);
1803  }
1804 
1805  // inserts a new element before or after the location pointed to by an
1806  // iterator
1807  template < typename Val, typename Alloc >
1809  Val&& val,
1810  location place) {
1811  return insert__(iter, createBucket__(std::move(val)), place);
1812  }
1813 
1814  // emplace a new element before a given iterator
1815  template < typename Val, typename Alloc >
1816  template < typename... Args >
1818  Args&&... args) {
1819  return insert__(iter,
1821  location::BEFORE);
1822  }
1823 
1824  // emplace a new element before a given iterator
1825  template < typename Val, typename Alloc >
1826  template < typename... Args >
1828  Args&&... args) {
1829  return insert__(iter,
1831  location::BEFORE);
1832  }
1833 
1834  // returns a reference to first element of a list
1835  template < typename Val, typename Alloc >
1836  INLINE Val& List< Val, Alloc >::front() const {
1837  if (nb_elements__ == Size(0)) {
1838  GUM_ERROR(NotFound, "not enough elements in the chained list");
1839  }
1840 
1841  return deb_list__->val__;
1842  }
1843 
1844  // returns a reference to last element of a list
1845  template < typename Val, typename Alloc >
1846  INLINE Val& List< Val, Alloc >::back() const {
1847  if (nb_elements__ == Size(0)) {
1848  GUM_ERROR(NotFound, "not enough elements in the chained list");
1849  }
1850 
1851  return end_list__->val__;
1852  }
1853 
1854  // returns the number of elements in the list.
1855  template < typename Val, typename Alloc >
1856  INLINE Size List< Val, Alloc >::size() const noexcept {
1857  return nb_elements__;
1858  }
1859 
1860  // checks whether there exists a given element in the list.
1861  template < typename Val, typename Alloc >
1862  INLINE bool List< Val, Alloc >::exists(const Val& val) const {
1863  for (ListBucket< Val >* ptr = deb_list__; ptr != nullptr; ptr = ptr->next__)
1864  if (ptr->val__ == val) return true;
1865 
1866  return false;
1867  }
1868 
1869  // suppresses a given bucket from a chained list.
1870  template < typename Val, typename Alloc >
1872  // perform deletion only if there is a bucket to remove
1873  if (bucket != nullptr) {
1874  // update the iterators pointing on this element
1875  for (const auto ptr_iter: safe_iterators__) {
1876  if (ptr_iter->bucket__ == bucket) {
1879  ptr_iter->bucket__ = nullptr;
1880  ptr_iter->null_pointing__ = true;
1881  } else {
1882  if (ptr_iter->null_pointing__) {
1885 
1888  }
1889  }
1890  }
1891 
1892  // set properly the begin and end of the chained list (the other chainings
1893  // will be performed by operator delete)
1894  if (bucket->prev__ == nullptr)
1896  else
1898 
1899  if (bucket->next__ == nullptr)
1901  else
1903 
1904  // remove the current element src the list
1907 
1908  --nb_elements__;
1909  }
1910  }
1911 
1912  // erases the ith element of the List (the first one is in position 0)
1913  template < typename Val, typename Alloc >
1914  INLINE void List< Val, Alloc >::erase(Size i) {
1915  if (i >= nb_elements__) return;
1916 
1917  // erase the ith bucket
1919  }
1920 
1921  // erases the element of the List pointed to by the iterator
1922  template < typename Val, typename Alloc >
1925  }
1926 
1927  // erases the element of the List pointed to by the iterator
1928  template < typename Val, typename Alloc >
1931  }
1932 
1933  // returns the bucket corresponding to a given value.
1934  template < typename Val, typename Alloc >
1935  INLINE ListBucket< Val >*
1936  List< Val, Alloc >::getBucket__(const Val& val) const noexcept {
1937  for (ListBucket< Val >* ptr = deb_list__; ptr != nullptr; ptr = ptr->next__)
1938  if (ptr->val__ == val) return ptr;
1939 
1940  return nullptr;
1941  }
1942 
1943  // erases the first element encountered with a given value
1944  template < typename Val, typename Alloc >
1945  INLINE void List< Val, Alloc >::eraseByVal(const Val& val) {
1947  }
1948 
1949  // erases all the elements encountered with a given value
1950  template < typename Val, typename Alloc >
1951  INLINE void List< Val, Alloc >::eraseAllVal(const Val& val) {
1952  for (ListBucket< Val >*iter = deb_list__, *next_bucket = nullptr;
1953  iter != nullptr;
1954  iter = next_bucket) {
1955  next_bucket = iter->next__;
1956 
1957  if (val == iter->val__) erase__(iter);
1958  }
1959  }
1960 
1961  // removes the last element of a List
1962  template < typename Val, typename Alloc >
1963  INLINE void List< Val, Alloc >::popBack() {
1965  }
1966 
1967  // removes the first element of a List
1968  template < typename Val, typename Alloc >
1969  INLINE void List< Val, Alloc >::popFront() {
1971  }
1972 
1973  // returns a boolean indicating whether the chained list is empty
1974  template < typename Val, typename Alloc >
1975  INLINE bool List< Val, Alloc >::empty() const noexcept {
1976  return (nb_elements__ == Size(0));
1977  }
1978 
1979  // displays the content of a chained list
1980  template < typename Val, typename Alloc >
1981  std::string List< Val, Alloc >::toString() const {
1982  bool deja = false;
1984  stream << "[";
1985 
1986  for (ListBucket< Val >* ptr = deb_list__; ptr != nullptr;
1987  ptr = ptr->next__, deja = true) {
1988  if (deja) stream << " --> ";
1989 
1990  stream << ptr->val__;
1991  }
1992 
1993  stream << "]";
1994 
1995  return stream.str();
1996  }
1997 
1998  // creates a list of mountains src a list of val
1999  template < typename Val, typename Alloc >
2000  template < typename Mount, typename OtherAlloc >
2001  List< Mount, OtherAlloc > List< Val, Alloc >::map(Mount (*f)(Val)) const {
2002  // create a new empty list
2003  List< Mount, OtherAlloc > list;
2004 
2005  // fill the new list
2006  for (const_iterator iter = begin(); iter != end(); ++iter) {
2007  list.pushBack(f(*iter));
2008  }
2009 
2010  return list;
2011  }
2012 
2013  // creates a list of mountains src a list of val
2014  template < typename Val, typename Alloc >
2015  template < typename Mount, typename OtherAlloc >
2016  List< Mount, OtherAlloc > List< Val, Alloc >::map(Mount (*f)(Val&)) const {
2017  // create a new empty list
2018  List< Mount, OtherAlloc > list;
2019 
2020  // fill the new list
2021  for (const_iterator iter = begin(); iter != end(); ++iter) {
2022  list.pushBack(f(*iter));
2023  }
2024 
2025  return list;
2026  }
2027 
2028  // creates a list of mountains src a list of val
2029  template < typename Val, typename Alloc >
2030  template < typename Mount, typename OtherAlloc >
2031  List< Mount, OtherAlloc > List< Val, Alloc >::map(Mount (*f)(const Val&)) const {
2032  // create a new empty list
2033  List< Mount, OtherAlloc > list;
2034 
2035  // fill the new list
2036  for (const_iterator iter = begin(); iter != end(); ++iter) {
2037  list.pushBack(f(*iter));
2038  }
2039 
2040  return list;
2041  }
2042 
2043  // creates a list of mountains with a given value src a list of val
2044  template < typename Val, typename Alloc >
2045  template < typename Mount, typename OtherAlloc >
2046  List< Mount, OtherAlloc > List< Val, Alloc >::map(const Mount& mount) const {
2047  // create a new empty list
2048  List< Mount, OtherAlloc > list;
2049 
2050  // fill the new list
2051  for (Size i = Size(0); i < nb_elements__; ++i)
2052  list.pushBack(mount);
2053 
2054  return list;
2055  }
2056 
2057  // creates and insert a new element at the end of the list (alias of
2058  // pushBack).
2059  template < typename Val, typename Alloc >
2060  INLINE Val& List< Val, Alloc >::operator+=(const Val& val) {
2061  return pushBack(val);
2062  }
2063 
2064  // creates and insert a new element at the end of the list (alias of
2065  // pushBack).
2066  template < typename Val, typename Alloc >
2068  return pushBack(std::move(val));
2069  }
2070 
2071  // checks whether two lists are identical (same elements in the same order)
2072  template < typename Val, typename Alloc >
2073  template < typename OtherAlloc >
2074  INLINE bool
2075  List< Val, Alloc >::operator==(const List< Val, OtherAlloc >& src) const {
2076  // check if the two lists have at least the same number of elements
2077  if (nb_elements__ != src.nb_elements__) return false;
2078 
2079  // parse the two lists
2081  iter1 != nullptr;
2083  if (*iter1 != *iter2) return false;
2084 
2085  return true;
2086  }
2087 
2088  // checks whether two lists are different (different elements or orders)
2089  template < typename Val, typename Alloc >
2090  template < typename OtherAlloc >
2091  INLINE bool
2092  List< Val, Alloc >::operator!=(const List< Val, OtherAlloc >& src) const {
2093  return !operator==(src);
2094  }
2095 
2096  // returns the ith element in the current chained list.
2097  template < typename Val, typename Alloc >
2098  INLINE Val& List< Val, Alloc >::operator[](const Size i) {
2099  // check if we can return the element we ask for
2100  if (i >= nb_elements__) {
2101  GUM_ERROR(NotFound, "not enough elements in the chained list");
2102  }
2103 
2104  return **getIthBucket__(i);
2105  }
2106 
2107  // returns the ith element in the current chained list.
2108  template < typename Val, typename Alloc >
2109  INLINE const Val& List< Val, Alloc >::operator[](const Size i) const {
2110  // check if we can return the element we ask for
2111  if (i >= nb_elements__) {
2112  GUM_ERROR(NotFound, "not enough elements in the chained list");
2113  }
2114 
2115  return **getIthBucket__(i);
2116  }
2117 
2118  // replace the current list with another one
2119  template < typename Val, typename Alloc >
2126  }
2127 
2128  // A \c << operator for List
2129  template < typename Val >
2131  stream << list.toString();
2132  return stream;
2133  }
2134 
2135 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669