DynamicListI.H
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2016-2025 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "FixedList.H"
30 
31 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
32 
33 template<class T, int SizeMin>
34 template<class ListType>
36 (
37  const ListType& list
38 )
39 {
40  const label len = list.size();
41 
42  if (capacity_ < len)
43  {
44  // Needs more space for the copy operation
45  List<T>::setAddressableSize(capacity_);
46  List<T>::resize_nocopy(len);
47  capacity_ = List<T>::size();
48  }
49 
50  // Perform copy into addressable portion
51  List<T>::setAddressableSize(len);
52  List<T>::operator=(list);
53 }
54 
55 
56 template<class T, int SizeMin>
58 (
59  const bool nocopy,
60  const label newCapacity
61 )
62 {
63  if (newCapacity == capacity_)
64  {
65  return;
66  }
67 
68  // Addressable length, possibly truncated by new capacity
69  const label currLen = Foam::min(List<T>::size(), newCapacity);
70 
71  List<T>::setAddressableSize(capacity_);
72  if (nocopy)
73  {
74  List<T>::resize_nocopy(newCapacity);
75  }
76  else
77  {
78  List<T>::resize_copy(currLen, newCapacity);
79  }
80 
81  capacity_ = List<T>::size();
82  List<T>::setAddressableSize(currLen);
83 }
84 
85 
86 template<class T, int SizeMin>
88 (
89  const bool nocopy,
90  const label len
91 )
92 {
93  if (capacity_ < len)
94  {
95  // Preserve addressed size
96  const label currLen = List<T>::size();
97 
98  // Increase capacity (eg, doubling)
99  capacity_ =
100  Foam::ListPolicy::reserve_size<SizeMin, 2>(len, capacity_);
101 
102  if (nocopy)
103  {
104  List<T>::resize_nocopy(capacity_);
105  }
106  else
107  {
108  List<T>::resize(capacity_);
109  }
110  List<T>::setAddressableSize(currLen);
111  }
112 }
113 
114 
115 template<class T, int SizeMin>
117 (
118  const bool nocopy,
119  const label len
120 )
121 {
122  this->doReserve(nocopy, len);
124 }
125 
126 
127 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
128 
129 template<class T, int SizeMin>
131 :
132  List<T>(),
133  capacity_(0)
134 {}
135 
136 
137 template<class T, int SizeMin>
138 inline Foam::DynamicList<T, SizeMin>::DynamicList(const label initialCapacity)
139 :
140  List<T>(),
141  capacity_(0)
142 {
143  reserve_nocopy(initialCapacity);
144 }
145 
146 
147 template<class T, int SizeMin>
149 (
150  const std::pair<label,label>& sizing
151 )
152 :
153  List<T>(std::max(sizing.first, sizing.second)),
154  capacity_(List<T>::size())
155 {
156  List<T>::setAddressableSize(sizing.first);
157 }
158 
159 
160 template<class T, int SizeMin>
162 (
163  const label len,
164  const T& val
165 )
166 :
167  List<T>(len, val),
168  capacity_(List<T>::size())
169 {}
170 
171 
172 template<class T, int SizeMin>
174 (
175  const label len,
176  Foam::zero
177 )
178 :
179  List<T>(len, Foam::zero{}),
180  capacity_(List<T>::size())
181 {}
182 
183 
184 template<class T, int SizeMin>
186 (
187  const DynamicList<T, SizeMin>& list
188 )
189 :
190  List<T>(list),
191  capacity_(List<T>::size())
192 {}
193 
194 
195 template<class T, int SizeMin>
196 template<int AnySizeMin>
198 (
199  const DynamicList<T, AnySizeMin>& list
200 )
201 :
202  List<T>(list),
203  capacity_(List<T>::size())
204 {}
205 
206 
207 template<class T, int SizeMin>
209 (
210  const UList<T>& list
211 )
212 :
213  List<T>(list),
214  capacity_(List<T>::size())
215 {}
216 
217 
218 template<class T, int SizeMin>
220 (
221  const UList<T>& list,
222  const labelUList& indices
223 )
224 :
225  List<T>(list, indices),
226  capacity_(List<T>::size())
227 {}
228 
229 
230 template<class T, int SizeMin>
231 template<unsigned N>
233 (
234  const FixedList<T, N>& list
235 )
236 :
237  List<T>(list),
238  capacity_(List<T>::size())
239 {}
240 
241 
242 template<class T, int SizeMin>
244 (
245  std::initializer_list<T> lst
246 )
247 :
248  List<T>(lst),
249  capacity_(List<T>::size())
250 {}
251 
252 
253 template<class T, int SizeMin>
254 template<class Addr>
256 (
257  const IndirectListBase<T, Addr>& lst
258 )
259 :
260  List<T>(lst),
261  capacity_(List<T>::size())
262 {}
263 
264 
265 template<class T, int SizeMin>
267 (
269 ) noexcept
270 :
271  List<T>(std::move(static_cast<List<T>&>(list))),
272  capacity_(list.capacity())
273 {
274  list.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
275 }
276 
277 
278 template<class T, int SizeMin>
279 template<int AnySizeMin>
281 (
283 ) noexcept
284 :
285  List<T>(std::move(static_cast<List<T>&>(list))),
286  capacity_(list.capacity())
287 {
288  list.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
289 }
290 
291 
292 template<class T, int SizeMin>
294 (
295  List<T>&& list
296 ) noexcept
297 :
298  List<T>(std::move(list)),
299  capacity_(List<T>::size())
300 {}
301 
302 
303 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
304 
305 template<class T, int SizeMin>
306 inline std::streamsize
308 {
309  return std::streamsize(capacity_)*sizeof(T);
310 }
311 
312 
313 template<class T, int SizeMin>
315 (
316  const label len
317 )
318 {
319  this->doCapacity(false, len); // nocopy = false
320 }
321 
322 
323 template<class T, int SizeMin>
325 (
326  const label len
327 )
328 {
329  this->doCapacity(true, len); // nocopy = true
330 }
331 
332 
333 template<class T, int SizeMin>
335 (
336  const label len
337 )
338 {
339  this->doReserve(false, len); // nocopy = false
340 }
341 
342 
343 template<class T, int SizeMin>
345 (
346  const label len
347 )
348 {
349  this->doReserve(true, len); // nocopy = true
350 }
351 
352 
353 template<class T, int SizeMin>
355 (
356  const label len
357 )
358 {
359  if (capacity_ < len)
360  {
361  // Preserve addressed size
362  const label currLen = List<T>::size();
363 
364  capacity_ = len;
365  List<T>::resize(capacity_);
367  }
368 }
369 
370 
371 template<class T, int SizeMin>
373 (
374  const label len
375 )
376 {
377  this->doResize(false, len); // nocopy = false
378 }
379 
380 
381 template<class T, int SizeMin>
383 (
384  const label len,
385  const T& val
386 )
387 {
388  this->doResize(true, len); // nocopy = true
389  UList<T>::operator=(val);
390 }
391 
392 
393 template<class T, int SizeMin>
395 (
396  const label len
397 )
398 {
399  this->doResize(true, len); // nocopy = true
400 }
401 
402 
403 template<class T, int SizeMin>
405 (
406  const label len,
407  const T& val
408 )
409 {
410  const label oldLen = List<T>::size();
411  resize(len);
412 
413  // Fill newly exposed with constant value
414  if (oldLen < List<T>::size())
415  {
416  std::fill
417  (
418  this->begin(oldLen), this->end(), val
419  );
420  }
421 }
422 
423 
424 template<class T, int SizeMin>
426 {
428 }
429 
430 
431 template<class T, int SizeMin>
433 {
434  List<T>::clear();
435  capacity_ = 0;
436 }
437 
438 
439 template<class T, int SizeMin>
441 {
442  const label currLen = List<T>::size();
443  if (currLen < capacity_)
444  {
445  List<T>::setAddressableSize(capacity_);
446  List<T>::resize(currLen);
447  capacity_ = List<T>::size();
448  }
449 }
450 
451 
452 template<class T, int SizeMin>
454 {
455  if (List<T>::empty())
456  {
457  // Delete storage if empty
458  List<T>::clear();
459  }
460  capacity_ = List<T>::size();
461 }
462 
463 
464 template<class T, int SizeMin>
465 inline void
467 {
468  if
469  (
470  static_cast<const List<T>*>(this)
471  == static_cast<const List<T>*>(&list)
472  )
473  {
474  return; // Self-swap is a no-op
475  }
476 
477  // Remove unused storage
478  this->shrink_to_fit();
479 
480  // Swap storage and addressable size
481  UList<T>::swap(list);
482 
483  // Update capacity
484  capacity_ = List<T>::size();
485 }
486 
487 
488 template<class T, int SizeMin>
489 template<int AnySizeMin>
491 (
493 ) noexcept
494 {
495  if
496  (
497  static_cast<const List<T>*>(this)
498  == static_cast<const List<T>*>(&other)
499  )
500  {
501  return; // Self-swap is a no-op
502  }
503 
504  // Swap storage and addressable size
505  UList<T>::swap(other);
506 
507  // Swap capacity
508  std::swap(this->capacity_, other.capacity_);
509 }
510 
511 
512 template<class T, int SizeMin>
513 inline void
515 {
516  List<T>::transfer(list);
517  capacity_ = List<T>::size();
518 }
519 
520 
521 template<class T, int SizeMin>
522 template<int AnySizeMin>
523 inline void
525 (
527 )
528 {
529  if
530  (
531  static_cast<const List<T>*>(this)
532  == static_cast<const List<T>*>(&list)
533  )
534  {
535  return; // Self-assignment is a no-op
536  }
537 
538  // Take over storage as-is (without shrink)
539  capacity_ = list.capacity();
540 
541  List<T>::transfer(static_cast<List<T>&>(list));
542  list.clearStorage(); // capacity=0 etc.
543 }
544 
545 
546 template<class T, int SizeMin>
547 template<class... Args>
549 {
550  // This could/should be better with inplace construction
551  // (as per std::vector), but currently lacking the methods for that
552  // so resize and move assign
553 
554  const label idx = List<T>::size();
555  resize(idx + 1);
556 
557  // move assign element
558  UList<T>::operator[](idx) = T(std::forward<Args>(args)...);
559  return UList<T>::operator[](idx);
560 }
561 
562 
563 template<class T, int SizeMin>
565 (
566  const T& val
567 )
568 {
569  const label idx = List<T>::size();
570  resize(idx + 1);
572  UList<T>::operator[](idx) = val; // copy element
573 }
574 
575 
576 template<class T, int SizeMin>
578 (
579  T&& val
580 )
581 {
582  const label idx = List<T>::size();
583  resize(idx + 1);
585  UList<T>::operator[](idx) = std::move(val); // move assign element
586 }
587 
588 
589 template<class T, int SizeMin>
591 (
592  const UList<T>& list
593 )
594 {
595  if (FOAM_UNLIKELY(this == &list))
596  {
598  << "Attempted push_back to self"
599  << abort(FatalError);
600  }
601 
602  const label idx = List<T>::size();
603  resize(idx + list.size());
604 
605  std::copy(list.begin(), list.end(), this->begin(idx));
606 }
607 
608 
609 template<class T, int SizeMin>
610 template<unsigned N>
612 (
613  const FixedList<T, N>& list
614 )
615 {
616  const label idx = List<T>::size();
617  resize(idx + list.size());
619  std::copy(list.begin(), list.end(), this->begin(idx));
620 }
621 
622 
623 template<class T, int SizeMin>
625 (
626  std::initializer_list<T> list
627 )
628 {
629  const label idx = List<T>::size();
630  resize(idx + list.size());
631 
632  std::copy(list.begin(), list.end(), this->begin(idx));
633 }
634 
635 
636 template<class T, int SizeMin>
637 template<class Addr>
639 (
640  const IndirectListBase<T, Addr>& list
641 )
642 {
643  // Note: push_back will still work even if the indirect list
644  // actually references *this, since its source elements will not
645  // overlap the new destinations.
646 
647  const label idx = this->size();
648  const label n = list.size();
649  resize(idx + n);
650 
651  auto iter = this->begin(idx);
652 
653  for (label i = 0; i < n; (void)++i, (void)++iter)
654  {
655  *iter = list[i]; // copy element
656  }
657 }
658 
659 
660 template<class T, int SizeMin>
662 (
663  List<T>&& list
664 )
665 {
666  if (FOAM_UNLIKELY(this == &list))
667  {
669  << "Attempted push_back to self"
670  << abort(FatalError);
671  }
672 
673  const label idx = List<T>::size();
674  resize(idx + list.size());
675 
676  std::move(list.begin(), list.end(), this->begin(idx));
677 
678  list.clear();
679 }
680 
681 
682 template<class T, int SizeMin>
683 template<int AnySizeMin>
685 (
687 )
688 {
689  push_back(std::move(static_cast<List<T>&>(list)));
690  list.clearStorage(); // Deletion, capacity=0 etc.
691 }
692 
693 
694 template<class T, int SizeMin>
695 inline Foam::label Foam::DynamicList<T, SizeMin>::push_uniq(const T& val)
696 {
697  if (this->contains(val))
698  {
699  return 0;
700  }
701  else
702  {
703  this->push_back(val);
704  return 1; // Increased list length by one
705  }
706 }
707 
708 
709 template<class T, int SizeMin>
711 {
712  if (n >= this->size())
713  {
714  clear();
715  }
716  else if (n > 0)
717  {
718  resize(this->size() - n);
719  }
720 }
721 
722 
723 template<class T, int SizeMin>
725 {
726  // Location of last element and simultaneously the new size
727  const label idx = List<T>::size() - 1;
728 
729  if (idx < 0)
730  {
732  << "List is empty" << abort(FatalError);
733  }
734 
735  const T& val = List<T>::operator[](idx);
736 
737  List<T>::setAddressableSize(idx);
739  return val;
740 }
741 
742 
743 template<class T, int SizeMin>
745 (
746  const label idx,
747  const bool fast
748 )
749 {
750  if (fast)
751  {
752  // Simply swap idx <=> last
753  this->swapLast(idx);
754  }
755  else
756  {
757  // Move element to the end and move everything down
758  this->moveLast(idx);
759  }
760 
761  // Element to remove is now at the end
762  return this->remove();
763 }
764 
765 
766 template<class T, int SizeMin>
767 inline Foam::label Foam::DynamicList<T, SizeMin>::remove
768 (
769  const labelRange& range
770 )
771 {
772  return this->removeElements(this->validateRange(range));
773 }
774 
775 
776 template<class T, int SizeMin>
777 inline Foam::label Foam::DynamicList<T, SizeMin>::remove
778 (
779  std::initializer_list<label> start_size
780 )
781 {
782  return this->removeElements(this->validateRange(start_size));
783 }
784 
785 
786 template<class T, int SizeMin>
787 inline Foam::label Foam::DynamicList<T, SizeMin>::subset
788 (
789  const labelRange& range
790 )
791 {
792  return this->subsetElements(this->validateRange(range));
793 }
794 
795 
796 template<class T, int SizeMin>
797 inline Foam::label Foam::DynamicList<T, SizeMin>::subset
798 (
799  std::initializer_list<label> start_size
800 )
801 {
802  return this->subsetElements(this->validateRange(start_size));
803 }
804 
805 
806 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
807 
808 template<class T, int SizeMin>
810 (
811  const label i
812 )
813 {
814  if (i >= List<T>::size())
815  {
816  resize(i + 1);
817  }
819  return UList<T>::operator[](i);
820 }
821 
822 
823 template<class T, int SizeMin>
825 (
826  const T& val
827 )
828 {
829  UList<T>::operator=(val);
830 }
831 
832 
833 template<class T, int SizeMin>
835 (
836  Foam::zero
837 )
838 {
840 }
841 
842 
843 template<class T, int SizeMin>
845 (
846  const UList<T>& lst
847 )
848 {
849  doAssignDynList(lst);
850 }
851 
852 
853 template<class T, int SizeMin>
854 template<unsigned N>
856 (
857  const FixedList<T, N>& lst
858 )
859 {
860  doAssignDynList(lst);
861 }
862 
863 
864 template<class T, int SizeMin>
866 (
867  const DynamicList<T, SizeMin>& lst
868 )
869 {
870  if (this == &lst)
871  {
872  return; // Self-assignment is a no-op
873  }
874 
875  doAssignDynList(lst);
876 }
877 
878 
879 template<class T, int SizeMin>
880 template<int AnySizeMin>
882 (
883  const DynamicList<T, AnySizeMin>& list
884 )
885 {
886  if
887  (
888  static_cast<const List<T>*>(this)
889  == static_cast<const List<T>*>(&list)
890  )
891  {
892  return; // Self-assignment is a no-op
893  }
895  doAssignDynList(list);
896 }
897 
898 
899 template<class T, int SizeMin>
901 (
902  std::initializer_list<T> lst
903 )
904 {
905  doAssignDynList(lst);
906 }
907 
908 
909 template<class T, int SizeMin>
910 template<class Addr>
912 (
913  const IndirectListBase<T, Addr>& lst
914 )
915 {
916  // NOTE: Self-assignment needs special handling
923  doAssignDynList(lst);
924 }
925 
926 
927 template<class T, int SizeMin>
929 (
930  List<T>&& lst
931 )
932 {
933  clear();
934  transfer(lst);
935 }
936 
937 
938 template<class T, int SizeMin>
940 (
942 )
943 {
944  if (this == &lst)
945  {
946  return; // Self-assignment is a no-op
947  }
948 
949  clear();
950  transfer(lst);
951 }
952 
953 
954 template<class T, int SizeMin>
955 template<int AnySizeMin>
957 (
959 )
960 {
961  if
962  (
963  static_cast<const List<T>*>(this)
964  == static_cast<const List<T>*>(&list)
965  )
966  {
967  return; // Self-assignment is a no-op
968  }
969 
970  clear();
971  transfer(list);
972 }
973 
974 
975 // ************************************************************************* //
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
friend Ostream & operator(Ostream &os, const DynamicList< T, SizeMin > &list)
Write to Ostream.
patchWriters resize(patchIds.size())
A 1D vector of objects of type <T> with a fixed length <N>.
Definition: HashTable.H:107
iterator begin() noexcept
Return an iterator to begin traversing the FixedList.
Definition: FixedListI.H:473
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:600
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
void reserve_nocopy(const label len)
Reserve allocation space for at least this size, allocating new space if required without retaining o...
Definition: DynamicListI.H:338
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
constexpr DynamicList() noexcept
Default construct, an empty list without allocation.
Definition: DynamicListI.H:123
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:52
void shrink_unsafe()
Shrink the internal bookkeeping of the allocated space to the number of addressed elements without af...
Definition: DynamicListI.H:446
void resize(const label len)
Alter addressable list size, allocating new space if required while recovering old content...
Definition: DynamicListI.H:366
iterator end() noexcept
Return an iterator to end traversing the FixedList.
Definition: FixedListI.H:521
void setCapacity(const label len)
Alter the size of the underlying storage.
Definition: DynamicListI.H:308
void resize_fill(const label len, const T &val)
Alter addressable size and set val for all addressed entries.
Definition: DynamicListI.H:376
void pop_back(label n=1)
Reduce size by 1 or more elements. Can be called on an empty list.
Definition: DynamicListI.H:703
Base for lists with indirect addressing, templated on the list contents type and the addressing type...
scalar range
void shrink_to_fit()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:433
label capacity() const noexcept
Size of the underlying storage.
Definition: DynamicList.H:236
static constexpr label size() noexcept
Return the number of elements in the FixedList.
Definition: FixedList.H:619
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:51
T & emplace_back(Args &&... args)
Construct an element at the end of the list, return reference to the new list element.
Definition: DynamicListI.H:541
std::streamsize capacity_bytes() const noexcept
Number of contiguous bytes of the underlying storage.
Definition: DynamicListI.H:300
#define FOAM_UNLIKELY(cond)
Definition: stdFoam.H:64
label size() const noexcept
The number of elements in the list.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
errorManip< error > abort(error &err)
Definition: errorManip.H:139
iterator begin() noexcept
Return an iterator to begin traversing the UList.
Definition: UListI.H:385
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:105
void reserve(const label len)
Reserve allocation space for at least this size, allocating new space if required and retaining old c...
Definition: DynamicListI.H:328
const direction noexcept
Definition: scalarImpl.H:255
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:418
const volScalarField & T
void push_back(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:558
void swap(List< T > &list)
Swap with plain List content. Implies shrink_to_fit().
Definition: DynamicListI.H:459
label push_uniq(const T &val)
Append an element if not already in the list.
Definition: DynamicListI.H:688
T remove()
Remove and return the last element. Fatal on an empty list.
Definition: DynamicListI.H:717
surface1 clear()
const char * end
Definition: SVGTools.H:223
void transfer(List< T > &list)
Transfer contents of the argument List into this.
Definition: DynamicListI.H:507
void clearStorage()
Clear the list and delete storage.
Definition: DynamicListI.H:425
label subset(const labelRange &range)
Retain a (start,size) subset from the list.
Definition: DynamicListI.H:781
void reserve_exact(const label len)
Reserve allocation space for at least this size, allocating new space if required and retaining old c...
Definition: DynamicListI.H:348
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:57
label n
void resize_nocopy(const label len)
Alter addressable list size, allocating new space if required without necessarily recovering old cont...
Definition: DynamicListI.H:388
iterator end() noexcept
Return an iterator to end traversing the UList.
Definition: UListI.H:429
Foam::argList args(argc, argv)
void setCapacity_nocopy(const label len)
Alter the size of the underlying storage, without retaining old content.
Definition: DynamicListI.H:318
Namespace for OpenFOAM.