Loading...
Searching...
No Matches
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-------------------------------------------------------------------------------
11License
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
33template<class T, int SizeMin>
34template<class ListType>
35inline void Foam::DynamicList<T, SizeMin>::doAssignDynList
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
56template<class T, int SizeMin>
57inline void Foam::DynamicList<T, SizeMin>::doCapacity_copy
58(
59 label count,
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 = std::min(List<T>::size(), newCapacity);
70
71 // The count truncated by the new addressable range
72 count = std::min(count, currLen);
73
74 // Consistent allocated sizing
75 List<T>::setAddressableSize(capacity_);
76
77 if (count > 0)
78 {
79 List<T>::resize_copy(count, newCapacity);
80 }
81 else
82 {
83 List<T>::resize_nocopy(newCapacity);
84 }
85
86 capacity_ = List<T>::size();
87 List<T>::setAddressableSize(currLen);
88}
89
90
91template<class T, int SizeMin>
92inline void Foam::DynamicList<T, SizeMin>::doReserve_copy
93(
94 label count,
95 const label len
96)
97{
98 if (capacity_ < len)
99 {
100 // Preserve addressed size
101 const label currLen = List<T>::size();
102
103 // The count truncated by the addressable range
104 count = std::min(count, currLen);
105
106 // Consistent allocated sizing
107 List<T>::setAddressableSize(capacity_);
108
109 // Increase capacity (eg, doubling)
110 // - this may need better handling for when lists become very large
111 capacity_ =
113
114 if (count > 0)
115 {
116 List<T>::resize_copy(count, capacity_);
117 }
118 else
119 {
120 List<T>::resize_nocopy(capacity_);
121 }
122
123 capacity_ = List<T>::size();
124 List<T>::setAddressableSize(currLen);
126}
127
128
129// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
130
131template<class T, int SizeMin>
132inline constexpr Foam::DynamicList<T, SizeMin>::DynamicList() noexcept
134 List<T>(),
135 capacity_(0)
136{}
137
138
139template<class T, int SizeMin>
140inline Foam::DynamicList<T, SizeMin>::DynamicList(const label initialCapacity)
141:
142 List<T>(),
143 capacity_(0)
144{
145 reserve_nocopy(initialCapacity);
146}
147
148
149template<class T, int SizeMin>
151(
152 std::pair<label,label> sizing
153)
154:
155 List<T>(std::max(sizing.first, sizing.second)),
156 capacity_(List<T>::size())
157{
158 List<T>::setAddressableSize(sizing.first);
159}
160
161
162template<class T, int SizeMin>
164(
165 const label len,
166 const T& val
167)
169 List<T>(len, val),
170 capacity_(List<T>::size())
171{}
172
173
174template<class T, int SizeMin>
176(
177 const label len,
179)
181 List<T>(len, Foam::zero{}),
182 capacity_(List<T>::size())
183{}
184
185
186template<class T, int SizeMin>
188(
189 const DynamicList<T, SizeMin>& list
190)
191:
192 List<T>(list),
193 capacity_(List<T>::size())
194{}
195
196
197template<class T, int SizeMin>
198template<int AnySizeMin>
200(
202)
204 List<T>(list),
205 capacity_(List<T>::size())
206{}
207
208
209template<class T, int SizeMin>
211(
212 const UList<T>& list
213)
215 List<T>(list),
216 capacity_(List<T>::size())
217{}
218
219
220template<class T, int SizeMin>
222(
223 const UList<T>& list,
224 const labelUList& indices
225)
226:
227 List<T>(list, indices),
228 capacity_(List<T>::size())
229{}
230
231
232template<class T, int SizeMin>
233template<unsigned N>
235(
236 const FixedList<T, N>& list
237)
239 List<T>(list),
240 capacity_(List<T>::size())
241{}
242
243
244template<class T, int SizeMin>
247 std::initializer_list<T> lst
248)
249:
250 List<T>(lst),
251 capacity_(List<T>::size())
252{}
253
254
255template<class T, int SizeMin>
256template<class Addr>
258(
260)
262 List<T>(lst),
263 capacity_(List<T>::size())
264{}
265
266
267template<class T, int SizeMin>
271) noexcept
272:
273 List<T>(std::move(static_cast<List<T>&>(list))),
274 capacity_(list.capacity())
276 list.setCapacity_unsafe(0); // All contents moved
278
279
280template<class T, int SizeMin>
281template<int AnySizeMin>
283(
286:
287 List<T>(std::move(static_cast<List<T>&>(list))),
288 capacity_(list.capacity())
289{
290 list.setCapacity_unsafe(0); // All contents moved
291}
292
293
294template<class T, int SizeMin>
297 List<T>&& list
298) noexcept
299:
300 List<T>(std::move(list)),
301 capacity_(List<T>::size())
303
304
305// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
306
307template<class T, int SizeMin>
308inline std::streamsize
310{
311 return std::streamsize(capacity_)*sizeof(T);
312}
314
315template<class T, int SizeMin>
317(
318 const label len
319)
321 // Preserve all content
322 doCapacity_copy(List<T>::size(), len);
323}
324
325
326template<class T, int SizeMin>
328(
329 const label len
330)
332 // Preserve 0 content
333 doCapacity_copy(0, len);
335
336
337template<class T, int SizeMin>
340 const label len
341)
343 // Preserve all content
344 doReserve_copy(List<T>::size(), len);
345}
346
348template<class T, int SizeMin>
350(
351 const label len
352)
354 // Preserve 0 content
355 doReserve_copy(0, len);
356}
357
359template<class T, int SizeMin>
361(
362 const label len
363)
364{
365 if (capacity_ < len)
366 {
367 // Preserve addressed size
368 const label currLen = List<T>::size();
369
370 // Consistent allocated sizing
372
373 // Exact length
374 capacity_ = len;
375
376 // if (!nocopy)
377 {
378 List<T>::resize_copy(currLen, capacity_);
379 }
380
381 capacity_ = List<T>::size();
383 }
384}
385
386
387template<class T, int SizeMin>
389(
390 const label len
391)
393 // Preserve all content
395}
396
397
398template<class T, int SizeMin>
400(
401 label count,
402 const label len
403)
404{
405 // Preserve count elements
406 doReserve_copy(count, len);
408}
409
410
411template<class T, int SizeMin>
413(
414 const label len,
415 const T& val
416)
418 resize_nocopy(len);
420}
422
423template<class T, int SizeMin>
425(
426 const label len
427)
429 // Preserve 0 content
430 resize_copy(0, len);
431}
432
433
434template<class T, int SizeMin>
436(
437 const label len,
438 const T& val
439)
440{
441 const label oldLen = List<T>::size();
442
443 // Preserve all content
444 resize(len);
445
446 // Fill newly exposed with constant value
447 if (oldLen < List<T>::size())
448 {
449 std::fill
450 (
451 this->begin(oldLen), this->end(), val
452 );
453 }
454}
455
456
457template<class T, int SizeMin>
459{
461}
462
463
464template<class T, int SizeMin>
466{
467 // Extra safety...?
468 if (!List<T>::cdata() && List<T>::empty()) capacity_ = 0;
469
470 // Consistent allocated sizing
473 capacity_ = 0;
474}
475
476
477template<class T, int SizeMin>
479{
480 const label currLen = List<T>::size();
481 if (currLen < capacity_)
482 {
484 List<T>::resize(currLen);
485 capacity_ = List<T>::size();
486 }
487}
488
489
490template<class T, int SizeMin>
491inline void
493{
494 if
495 (
497 (
498 static_cast<const List<T>*>(this)
499 == static_cast<const List<T>*>(&other)
500 )
501 )
502 {
503 return; // Self-swap is a no-op
504 }
505
506 // Remove unused storage
507 this->shrink_to_fit();
508
509 // Swap storage and addressable size
510 UList<T>::swap(other);
511
512 // Update capacity
513 capacity_ = List<T>::size();
514}
515
516
517template<class T, int SizeMin>
518template<int AnySizeMin>
520(
522) noexcept
523{
524 if
525 (
527 (
528 static_cast<const List<T>*>(this)
529 == static_cast<const List<T>*>(&other)
530 )
531 )
532 {
533 return; // Self-swap is a no-op
534 }
535
536 // Swap storage and addressable size
537 UList<T>::swap(other);
538
539 // Swap capacity
540 std::swap(capacity_, other.capacity_);
541}
542
543
544template<class T, int SizeMin>
545inline void
547{
548 // No check for self-assignment (different types)
549
550 // Consistent allocated sizing
552 List<T>::transfer(list);
553 capacity_ = List<T>::size();
554}
555
556
557template<class T, int SizeMin>
558template<int AnySizeMin>
559inline void
561(
563)
564{
565 if
566 (
568 (
569 static_cast<const List<T>*>(this)
570 == static_cast<const List<T>*>(&other)
571 )
572 )
573 {
574 return; // Self-assignment is a no-op
575 }
576
577 // Consistent allocated sizing
578 List<T>::setAddressableSize(capacity_);
579 List<T>::transfer(static_cast<List<T>&>(other));
580
581 // Update capacity information
582 capacity_ = other.capacity();
583 other.setCapacity_unsafe(0); // All contents moved
584}
585
586
587template<class T, int SizeMin>
588template<class... Args>
590{
591 // This could/should be better with inplace construction
592 // (as per std::vector), but currently lacking the methods for that
593 // so resize and move assign
594
595 const label idx = List<T>::size();
596 resize(idx + 1);
597
598 // move assign element
599 UList<T>::operator[](idx) = T(std::forward<Args>(args)...);
600 return UList<T>::operator[](idx);
601}
602
603
604template<class T, int SizeMin>
606(
607 const T& val
608)
609{
610 const label idx = List<T>::size();
611 resize(idx + 1);
612
613 UList<T>::operator[](idx) = val; // copy element
614}
615
616
617template<class T, int SizeMin>
619(
620 T&& val
621)
622{
623 const label idx = List<T>::size();
624 resize(idx + 1);
625
626 UList<T>::operator[](idx) = std::move(val); // move assign element
627}
628
629
630template<class T, int SizeMin>
632(
633 const UList<T>& list
634)
635{
636 if
637 (
639 (
640 static_cast<const List<T>*>(this)
641 == static_cast<const List<T>*>(&list)
642 )
643 )
644 {
646 << "Attempted push_back to self"
647 << abort(FatalError);
648 }
649
650 const label idx = List<T>::size();
651 resize(idx + list.size());
653 std::copy(list.begin(), list.end(), this->begin(idx));
654}
655
656
657template<class T, int SizeMin>
658template<unsigned N>
660(
661 const FixedList<T, N>& list
662)
663{
664 const label idx = List<T>::size();
665 resize(idx + list.size());
666
667 std::copy(list.begin(), list.end(), this->begin(idx));
668}
669
670
671template<class T, int SizeMin>
673(
674 std::initializer_list<T> list
675)
676{
677 const label idx = List<T>::size();
678 resize(idx + list.size());
680 std::copy(list.begin(), list.end(), this->begin(idx));
681}
682
683
684template<class T, int SizeMin>
685template<class Addr>
687(
688 const IndirectListBase<T, Addr>& list
689)
690{
691 // Note: push_back will still work even if the indirect list
692 // actually references *this, since its source elements will not
693 // overlap the new destinations.
694
695 const label idx = this->size();
696 const label n = list.size();
697 resize(idx + n);
698
699 auto iter = this->begin(idx);
700
701 for (label i = 0; i < n; (void)++i, (void)++iter)
703 *iter = list[i]; // copy element
704 }
705}
706
707
708template<class T, int SizeMin>
710(
711 List<T>&& list
712)
713{
714 if
715 (
717 (
718 static_cast<const List<T>*>(this)
719 == static_cast<const List<T>*>(&list)
720 )
721 )
722 {
724 << "Attempted push_back to self"
725 << abort(FatalError);
726 }
727
728 const label idx = List<T>::size();
729 resize(idx + list.size());
730
731 // Move the elements
732 std::move(list.begin(), list.end(), this->begin(idx));
734 list.clear();
735}
736
737
738template<class T, int SizeMin>
739template<int AnySizeMin>
741(
743)
744{
745 if
746 (
748 (
749 static_cast<const List<T>*>(this)
750 == static_cast<const List<T>*>(&list)
751 )
752 )
753 {
755 << "Attempted push_back to self"
756 << abort(FatalError);
757 }
758
759 const label idx = List<T>::size();
760 resize(idx + list.size());
761
762 // Move the elements
763 std::move(list.begin(), list.end(), this->begin(idx));
764
765 list.clearStorage(); // Deletion, capacity=0 etc.
766}
767
768
769template<class T, int SizeMin>
770inline Foam::label Foam::DynamicList<T, SizeMin>::push_uniq(const T& val)
771{
772 if (this->contains(val))
773 {
774 return 0;
775 }
776 else
777 {
778 this->push_back(val);
779 return 1; // Increased list length by one
780 }
781}
782
783
784template<class T, int SizeMin>
786{
787 if (n >= this->size())
788 {
789 clear();
790 }
791 else if (n > 0)
793 resize(this->size() - n);
794 }
795}
796
797
798template<class T, int SizeMin>
800{
801 // Location of last element and simultaneously the new size
802 const label idx = List<T>::size() - 1;
803
804 if (idx < 0)
805 {
807 << "List is empty" << abort(FatalError);
808 }
809
810 const T& val = List<T>::operator[](idx);
811
813
814 return val;
815}
816
817
818template<class T, int SizeMin>
820(
821 const label idx,
822 const bool fast
823)
824{
825 if (fast)
826 {
827 // Simply swap idx <=> last
828 this->swapLast(idx);
829 }
830 else
831 {
832 // Move element to the end and move everything down
833 this->moveLast(idx);
834 }
836 // Element to remove is now at the end
837 return this->remove();
838}
839
840
841template<class T, int SizeMin>
843(
844 const labelRange& range
846{
847 return this->removeElements(this->validateRange(range));
848}
849
850
851template<class T, int SizeMin>
853(
854 std::initializer_list<label> start_size
856{
857 return this->removeElements(this->validateRange(start_size));
858}
859
860
861template<class T, int SizeMin>
863(
864 const labelRange& range
866{
867 return this->subsetElements(this->validateRange(range));
868}
869
870
871template<class T, int SizeMin>
873(
874 std::initializer_list<label> start_size
875)
876{
877 return this->subsetElements(this->validateRange(start_size));
878}
879
880
881// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
882
883template<class T, int SizeMin>
885(
886 const label i
887)
888{
889 if (i >= List<T>::size())
890 {
891 resize(i + 1);
893
894 return UList<T>::operator[](i);
895}
896
897
898template<class T, int SizeMin>
900(
901 const T& val
903{
905}
906
907
908template<class T, int SizeMin>
910(
913{
915}
916
917
918template<class T, int SizeMin>
920(
921 const UList<T>& lst
922)
924 doAssignDynList(lst);
925}
926
927
928template<class T, int SizeMin>
929template<unsigned N>
931(
932 const FixedList<T, N>& lst
934{
935 doAssignDynList(lst);
936}
937
938
939template<class T, int SizeMin>
941(
942 const DynamicList<T, SizeMin>& list
943)
944{
945 if
946 (
948 (
949 static_cast<const List<T>*>(this)
950 == static_cast<const List<T>*>(&list)
951 )
952 )
953 {
954 return; // Self-assignment is a no-op
955 }
957 doAssignDynList(list);
958}
959
960
961template<class T, int SizeMin>
962template<int AnySizeMin>
964(
966)
967{
968 if
969 (
971 (
972 static_cast<const List<T>*>(this)
973 == static_cast<const List<T>*>(&list)
974 )
975 )
976 {
977 return; // Self-assignment is a no-op
979
980 doAssignDynList(list);
981}
982
983
984template<class T, int SizeMin>
986(
987 std::initializer_list<T> lst
988)
990 doAssignDynList(lst);
991}
992
993
994template<class T, int SizeMin>
995template<class Addr>
997(
998 const IndirectListBase<T, Addr>& list
999)
1000{
1001 // NOTE: Self-assignment needs special handling
1002 // if
1003 // (
1004 // FOAM_UNLIKELY
1005 // (
1006 // static_cast<const UList<T>*>(this)
1007 // == static_cast<const UList<T>*>(&list.values())
1008 // )
1009 // )
1010 // { ... }
1011
1012 doAssignDynList(list);
1013}
1014
1015
1016template<class T, int SizeMin>
1018(
1019 List<T>&& list
1021{
1022 this->transfer(list);
1023}
1024
1025
1026template<class T, int SizeMin>
1028(
1030)
1032 this->transfer(list);
1033}
1034
1035
1036template<class T, int SizeMin>
1037template<int AnySizeMin>
1039(
1041)
1042{
1043 this->transfer(list);
1044}
1045
1046
1047// ************************************************************************* //
scalar range
label n
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
constexpr DynamicList() noexcept
Default construct, an empty list without allocation.
T remove()
Remove and return the last element. Fatal on an empty list.
void transfer(List< T > &list)
Transfer contents of the argument List into this.
void pop_back(label n=1)
Reduce size by 1 or more elements. Can be called on an empty list.
void resize_nocopy(const label len)
Alter addressable list size, allocating new space if required without necessarily recovering old cont...
void setCapacity_nocopy(const label len)
Alter the size of the underlying storage, without retaining old content.
T & emplace_back(Args &&... args)
Construct an element at the end of the list, return reference to the new list element.
void setCapacity_unsafe(label len) noexcept
Change the value for the list capacity directly (ADVANCED, UNSAFE) Does not perform any memory manage...
void reserve_nocopy(const label len)
Reserve allocation space for at least this size, allocating new space if required without retaining o...
void reserve_exact(const label len)
Reserve allocation space for at least this size, allocating new space if required and retaining old c...
std::streamsize capacity_bytes() const noexcept
Number of contiguous bytes of the underlying storage.
void resize_copy(label count, const label len)
Alter addressable size, retaining the first count contents.
void shrink_to_fit()
Shrink the allocated space to the number of elements used.
void swap(List< T > &other)
Swap with plain List content. Implies shrink_to_fit().
void clearStorage()
Clear the list and delete storage.
label push_uniq(const T &val)
Append an element if not already in the list.
void push_back(const T &val)
Copy append an element to the end of this list.
label capacity() const noexcept
Size of the underlying storage.
friend Ostream & operator(Ostream &os, const DynamicList< T, SizeMin > &list)
Write to Ostream.
void resize(const label len)
Alter addressable list size, allocating new space if required while recovering old content.
void reserve(const label len)
Reserve allocation space for at least this size, allocating new space if required and retaining old c...
label subset(const labelRange &range)
Retain a (start,size) subset from the list.
void resize_fill(const label len, const T &val)
Alter addressable size and set val for all addressed entries.
void setCapacity(const label len)
Alter the size of the underlying storage.
A 1D vector of objects of type <T> with a fixed length <N>.
Definition FixedList.H:73
static constexpr label size() noexcept
Return the number of elements in the FixedList.
Definition FixedList.H:619
iterator end() noexcept
Return an iterator to end traversing the FixedList.
Definition FixedListI.H:526
iterator begin() noexcept
Return an iterator to begin traversing the FixedList.
Definition FixedListI.H:478
Base for lists with indirect addressing, templated on the list contents type and the addressing type....
label size() const noexcept
The number of elements in the list.
iterator end()
Return an iterator at end of list.
iterator begin()
Return an iterator at begin of list.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
void transfer(List< T > &list)
Transfer the contents of the argument List into this list and annul the argument list.
Definition List.C:347
void resize_copy(label count, const label len)
Change allocated size of list, retaining the first count elements.
Definition List.C:31
void resize(const label len)
Adjust allocated size of list.
Definition ListI.H:153
void clear()
Clear the list, i.e. set size to zero.
Definition ListI.H:133
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition UList.H:89
void moveLast(const label i)
Move element to the last position.
Definition UList.C:57
void swapLast(const label i)
Swap element with the last element. Fatal on an empty list.
Definition UList.C:81
T & first()
Access first element of the list, position [0].
Definition UList.H:957
iterator begin() noexcept
Return an iterator to begin traversing the UList.
Definition UListI.H:410
bool empty() const noexcept
True if List is empty (ie, size() is zero).
Definition UList.H:701
bool contains(const T &val) const
True if the value is contained in the list.
Definition UListI.H:302
iterator end() noexcept
Return an iterator to end traversing the UList.
Definition UListI.H:454
const T * cdata() const noexcept
Return pointer to the underlying array serving as data storage.
Definition UListI.H:267
void swap(UList< T > &list) noexcept
Swap content with another UList of the same type in constant time.
Definition UListI.H:524
label size() const noexcept
The number of elements in the container.
Definition UList.H:706
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
void setAddressableSize(const label n) noexcept
Set addressed size to be inconsistent with allocated storage.
Definition UListI.H:517
T & operator[](const label i)
Return element of UList.
Definition UListI.H:363
labelRange validateRange(const labelRange &requestedRange) const
Return a validated (start,size) subset range, which means that it always addresses a valid section of...
Definition UList.C:29
UList< T > & operator=(const UList< T > &)=delete
No copy assignment (default: shallow copy).
A range or interval of labels defined by a start and a size.
Definition labelRange.H:66
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition zero.H:58
const volScalarField & T
patchWriters resize(patchIds.size())
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
surface1 clear()
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of 'true' entries.
Definition BitOps.H:73
IntType reserve_size(IntType requested, IntType capacity) noexcept
Calculate a reserve size (eg, doubling) based on the requested length and the current capacity.
Definition ListPolicy.H:293
Namespace for OpenFOAM.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
errorManip< error > abort(error &err)
Definition errorManip.H:139
const direction noexcept
Definition scalarImpl.H:265
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
UList< label > labelUList
A UList of labels.
Definition UList.H:75
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
Foam::argList args(argc, argv)
#define FOAM_UNLIKELY(cond)
Definition stdFoam.H:64