UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
Array.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
11
12namespace uLang
13{
14
15namespace Private
16{
17 template <typename FromArrayType, typename ToArrayType>
19 {
20 using FromAllocatorType = typename FromArrayType::ElementAllocatorType;
21 using ToAllocatorType = typename ToArrayType::ElementAllocatorType;
22 using FromElementType = typename FromArrayType::ElementType;
23 using ToElementType = typename ToArrayType::ElementType;
24
25 enum
26 {
27 Value =
29 TContainerTraits<FromArrayType>::MoveWillEmptyContainer && // A move must be allowed to leave the source array empty
30 (
31 TAreTypesEqual <ToElementType, FromElementType>::Value || // The element type of the container must be the same, or...
32 TIsBitwiseConstructible<ToElementType, FromElementType>::Value // ... the element type of the source container must be bitwise constructible from the element type in the destination container
33 )
34 };
35 };
36}
37
49template<typename InElementType, typename InElementAllocatorType, typename... RawAllocatorArgsType>
51{
52 template <typename OtherElementType, typename OtherElementAllocatorType, typename... OtherRawAllocatorArgsType>
53 friend class TArrayG;
54
55public:
56
59
68
72 ULANG_FORCEINLINE TArrayG(const typename ElementAllocatorType::RawAllocatorType & RawAllocator)
74 , _ArrayNum(0)
75 , _ArrayMax(0)
76 {}
77
87 {
88 ULANG_ASSERTF(Ptr != nullptr || Count == 0, "Attempted to construct array from invalid source data.");
89
90 CopyToEmpty(Ptr, Count, 0, 0);
91 }
92
95 {
97 ResizeForCopy(Count, 0);
98 for (ElementType* I = GetData(), * Last = I + Count; I != Last; ++I)
99 {
100 new (I) ElementType(Value);
101 }
102 }
103
107 TArrayG(std::initializer_list<InElementType> InitList, RawAllocatorArgsType&&... RawAllocatorArgs)
109 {
110 // This is not strictly legal, as std::initializer_list's iterators are not guaranteed to be pointers, but
111 // this appears to be the case on all of our implementations. Also, if it's not true on a new implementation,
112 // it will fail to compile rather than behave badly.
113 CopyToEmpty(InitList.begin(), (int32_t)InitList.size(), 0, 0);
114 }
115
117 template <typename OtherElementType>
119 {
120 CopyToEmpty(InitList.begin(), (int32_t) InitList.size(), 0, 0);
121 }
122
128 template <typename OtherElementType, typename OtherElementAllocatorType, typename... OtherRawAllocatorArgsType>
134
142 {
143 CopyToEmpty(Other.GetData(), Other.Num(), 0, 0);
144 }
145
155 {
156 CopyToEmpty(Other.GetData(), Other.Num(), 0, ExtraSlack);
157 }
158
166 {
167 if (this != &Other)
168 {
169 ULANG_ASSERTF(_ElementStorage.GetRawAllocator() == Other._ElementStorage.GetRawAllocator(), "Currently, can only assign between arrays using the same allocator.");
171 CopyToEmpty(Other.GetData(), Other.Num(), _ArrayMax, 0);
172 }
173 return *this;
174 }
175
176private:
177
186 template <typename FromArrayType, typename ToArrayType>
188 {
189 ToArray._ElementStorage.MoveToEmpty(FromArray._ElementStorage);
190
191 ToArray ._ArrayNum = FromArray._ArrayNum;
192 ToArray ._ArrayMax = FromArray._ArrayMax;
193 FromArray._ArrayNum = 0;
194 FromArray._ArrayMax = 0;
195 }
196
207 template <typename FromArrayType, typename ToArrayType>
209 {
210 ToArray._ElementStorage.SetRawAllocator(FromArray._ElementStorage.GetRawAllocator());
211 ToArray.CopyToEmpty(FromArray.GetData(), FromArray.Num(), PrevMax, 0);
212 }
213
224 template <typename FromArrayType, typename ToArrayType>
226 {
227 MoveOrCopy(ToArray, FromArray, PrevMax);
228
229 ToArray.Reserve(ToArray._ArrayNum + ExtraSlack);
230 }
231
242 template <typename FromArrayType, typename ToArrayType>
244 {
245 ToArray._ElementStorage.SetRawAllocator(FromArray._ElementStorage.GetRawAllocator());
246 ToArray.CopyToEmpty(FromArray.GetData(), FromArray.Num(), PrevMax, ExtraSlack);
247 }
248
249public:
256 {
257 MoveOrCopy(*this, Other, 0);
258 }
259
267 TArrayG(TArrayG && Other, int32_t ExtraSlack)
268 {
269 // We don't implement move semantics for general OtherAllocators, as there's no way
270 // to tell if they're compatible with the current one. Probably going to be a pretty
271 // rare requirement anyway.
272
273 MoveOrCopyWithSlack(*this, Other, 0, ExtraSlack);
274 }
275
281 template <typename OtherElementAllocatorType, typename... OtherRawAllocatorArgsType>
286
293 {
294 if (this != &Other)
295 {
297 MoveOrCopy(*this, Other, _ArrayMax);
298 }
299 return *this;
300 }
301
307
314 {
315 return (ElementType*)_ElementStorage.GetAllocation();
316 }
317
324 {
325 return (const ElementType*)_ElementStorage.GetAllocation();
326 }
327
334 {
335 return sizeof(ElementType);
336 }
337
346 {
347 return _ElementStorage.GetAllocatedSize(_ArrayMax, sizeof(ElementType));
348 }
349
356 {
357 return _ArrayMax - _ArrayNum;
358 }
359
365 {
366 ULANG_ASSERTF((_ArrayNum >= 0) & (_ArrayMax >= _ArrayNum), "Bad array configuration detected."); // & for one branch
367 }
368
375 {
377
378 // Template property, branch will be optimized out
379 if (ElementAllocatorType::RequireRangeCheck)
380 {
381 ULANG_ASSERTF((Index >= 0) & (Index < _ArrayNum), "Array index out of bounds: %i from an array of size %i", Index, _ArrayNum); // & for one branch
382 }
383 }
384
392 {
393 return Index >= 0 && Index < _ArrayNum;
394 }
395
403 {
404 return _ArrayNum;
405 }
406
414 {
415 return _ArrayMax;
416 }
417
419 ULANG_FORCEINLINE const typename ElementAllocatorType::RawAllocatorType & GetRawAllocator() const
420 {
421 return _ElementStorage.GetRawAllocator();
422 }
423
431 {
432 return _ArrayNum == 0;
433 }
434
442 {
443 return _ArrayNum != 0;
444 }
445
456
465 {
467 return GetData()[Index];
468 }
469
476 ULANG_FORCEINLINE ElementType Pop(bool bAllowShrinking = true)
477 {
478 RangeCheck(0);
480 RemoveAt(_ArrayNum - 1, 1, bAllowShrinking);
481 return Result;
482 }
483
490 {
492 }
493
503 {
504 Add(Item);
505 }
506
514 {
515 return Last();
516 }
517
527 {
528 return Last();
529 }
530
542
556
563 {
565 if (_ArrayMax != _ArrayNum)
566 {
567 ResizeTo(_ArrayNum);
568 }
569 }
570
580 {
581 Index = this->Find(Item);
582 return Index != IndexNone;
583 }
584
592 int32_t Find(const ElementType& Item) const
593 {
594 const ElementType* ULANG_RESTRICT Start = GetData();
595 for (const ElementType* ULANG_RESTRICT Data = Start, *ULANG_RESTRICT DataEnd = Data + _ArrayNum; Data != DataEnd; ++Data)
596 {
597 if (*Data == Item)
598 {
599 return static_cast<int32_t>(Data - Start);
600 }
601 }
602 return IndexNone;
603 }
604
614 {
615 Index = this->FindLast(Item);
616 return Index != IndexNone;
617 }
618
625 int32_t FindLast(const ElementType& Item) const
626 {
627 for (const ElementType* ULANG_RESTRICT Start = GetData(), *ULANG_RESTRICT Data = Start + _ArrayNum; Data != Start; )
628 {
629 --Data;
630 if (*Data == Item)
631 {
632 return static_cast<int32_t>(Data - Start);
633 }
634 }
635 return IndexNone;
636 }
637
645 template <typename Predicate>
647 {
648 ULANG_ASSERTF(Count >= 0 && Count <= this->Num(), "Bad range specified.");
649 for (const ElementType* ULANG_RESTRICT Start = GetData(), *ULANG_RESTRICT Data = Start + Count; Data != Start; )
650 {
651 --Data;
652 if (Pred(*Data))
653 {
654 return static_cast<int32_t>(Data - Start);
655 }
656 }
657 return IndexNone;
658 }
659
666 template <typename Predicate>
671
679 template <typename KeyType>
680 int32_t IndexOfByKey(const KeyType& Key) const
681 {
682 const ElementType* ULANG_RESTRICT Start = GetData();
683 for (const ElementType* ULANG_RESTRICT Data = Start, *ULANG_RESTRICT DataEnd = Start + _ArrayNum; Data != DataEnd; ++Data)
684 {
685 if (*Data == Key)
686 {
687 return static_cast<int32_t>(Data - Start);
688 }
689 }
690 return IndexNone;
691 }
692
699 template <typename Predicate>
701 {
702 const ElementType* ULANG_RESTRICT Start = GetData();
703 for (const ElementType* ULANG_RESTRICT Data = Start, *ULANG_RESTRICT DataEnd = Start + _ArrayNum; Data != DataEnd; ++Data)
704 {
705 if (Pred(*Data))
706 {
707 return static_cast<int32_t>(Data - Start);
708 }
709 }
710 return IndexNone;
711 }
712
721 template <typename KeyType>
722 ULANG_FORCEINLINE const ElementType* FindByKey(const KeyType& Key) const
723 {
724 return const_cast<TArrayG*>(this)->FindByKey(Key);
725 }
726
735 template <typename KeyType>
736 ElementType* FindByKey(const KeyType& Key)
737 {
738 for (ElementType* ULANG_RESTRICT Data = GetData(), *ULANG_RESTRICT DataEnd = Data + _ArrayNum; Data != DataEnd; ++Data)
739 {
740 if (*Data == Key)
741 {
742 return Data;
743 }
744 }
745
746 return nullptr;
747 }
748
756 template <typename Predicate>
758 {
759 return const_cast<TArrayG*>(this)->FindByPredicate(Pred);
760 }
761
768 template <typename Predicate>
770 {
771 for (ElementType* ULANG_RESTRICT Data = GetData(), *ULANG_RESTRICT DataEnd = Data + _ArrayNum; Data != DataEnd; ++Data)
772 {
773 if (Pred(*Data))
774 {
775 return Data;
776 }
777 }
778
779 return nullptr;
780 }
781
790 template <typename Predicate>
792 {
794 for (const ElementType* ULANG_RESTRICT Data = GetData(), *ULANG_RESTRICT DataEnd = Data + _ArrayNum; Data != DataEnd; ++Data)
795 {
796 if (Pred(*Data))
797 {
798 FilterResults.Add(*Data);
799 }
800 }
801 return FilterResults;
802 }
803
810 template <typename ComparisonType>
811 bool Contains(const ComparisonType& Item) const
812 {
813 for (const ElementType* ULANG_RESTRICT Data = GetData(), *ULANG_RESTRICT DataEnd = Data + _ArrayNum; Data != DataEnd; ++Data)
814 {
815 if (*Data == Item)
816 {
817 return true;
818 }
819 }
820 return false;
821 }
822
830 template <typename Predicate>
832 {
833 return FindByPredicate(Pred) != nullptr;
834 }
835
842 bool operator==(const TArrayG& OtherArray) const
843 {
844 int32_t Count = Num();
845
846 return Count == OtherArray.Num() && CompareElements(GetData(), OtherArray.GetData(), Count);
847 }
848
856 {
857 return !(*this == OtherArray);
858 }
859
871 {
873 ULANG_ASSERTF(Count >= 0, "Number of elements to add to array must not be negative.");
874
875 const int32_t OldNum = _ArrayNum;
876 if ((_ArrayNum += Count) > _ArrayMax)
877 {
878 ResizeGrow(OldNum);
879 }
880 return OldNum;
881 }
882
896 {
898 ULANG_ASSERTF((Count >= 0) & (Index >= 0) & (Index <= _ArrayNum), "Cannot insert elements into array due to invalid parameters.");
899
900 const int32_t OldNum = _ArrayNum;
901 if ((_ArrayNum += Count) > _ArrayMax)
902 {
903 ResizeGrow(OldNum);
904 }
905 ElementType* Data = GetData() + Index;
907 }
908
922 {
924 if (Count)
925 {
926 memset(GetData() + Index, 0, Count * sizeof(ElementType));
927 }
928 }
929
942 {
944 ElementType* Ptr = GetData() + Index;
945 memset(Ptr, 0, sizeof(ElementType));
946 return *Ptr;
947 }
948
962
978
986 int32_t Insert(std::initializer_list<ElementType> InitList, const int32_t InIndex)
987 {
989
992
993 return InIndex;
994 }
995
1003 template <typename OtherElementAllocatorType, typename... OtherRawAllocatorArgsType>
1005 {
1006 ULANG_ASSERTF((const void*)this != (const void*)&Items, "Attempted to insert array into itself.");
1007
1008 int32_t NumNewElements = Items.Num();
1009
1012
1013 return InIndex;
1014 }
1015
1023 template <typename OtherElementAllocatorType, typename... OtherRawAllocatorArgsType>
1025 {
1026 ULANG_ASSERTF((const void*)this != (const void*)&Items, "Attempted to insert array into itself.");
1027
1028 int32_t NumNewElements = Items.Num();
1029
1032 Items._ArrayNum = 0;
1033
1034 return InIndex;
1035 }
1036
1047 {
1048 ULANG_ASSERTF(Ptr != nullptr, "Elements to insert must not be null.");
1049
1052
1053 return Index;
1054 }
1055
1064 ULANG_FORCEINLINE void CheckAddress(void const* Addr) const
1065 {
1066 ULANG_ASSERTF(Addr < GetData() || Addr >= (GetData() + _ArrayMax), "Attempting to use a container element (%p) which already comes from the container being modified (%p, ArrayMax: %d, ArrayNum: %d, SizeofElement: %d)!", Addr, GetData(), _ArrayMax, _ArrayNum, sizeof(ElementType));
1067 }
1068
1079 {
1080 CheckAddress(&Item);
1081
1082 // construct a copy in place at Index (this new operator will insert at
1083 // Index, then construct that memory with Item)
1086 return Index;
1087 }
1088
1098 {
1099 CheckAddress(&Item);
1100
1101 // construct a copy in place at Index (this new operator will insert at
1102 // Index, then construct that memory with Item)
1104 new(GetData() + Index) ElementType(Item);
1105 return Index;
1106 }
1107
1118 {
1119 CheckAddress(&Item);
1120
1121 // construct a copy in place at Index (this new operator will insert at
1122 // Index, then construct that memory with Item)
1124 ElementType* Ptr = GetData() + Index;
1125 new(Ptr) ElementType(uLang::MoveIfPossible(Item));
1126 return *Ptr;
1127 }
1128
1138 {
1139 CheckAddress(&Item);
1140
1141 // construct a copy in place at Index (this new operator will insert at
1142 // Index, then construct that memory with Item)
1144 ElementType* Ptr = GetData() + Index;
1145 new(Ptr) ElementType(Item);
1146 return *Ptr;
1147 }
1148
1149private:
1150 void RemoveAtImpl(int32_t Index, int32_t Count, bool bAllowShrinking)
1151 {
1152 if (Count)
1153 {
1155 ULANG_ASSERTF((Count >= 0) & (Index >= 0) & (Index + Count <= _ArrayNum), "Cannot remove elements from array due to invalid parameters.");
1156
1158
1159 // Skip memmove in the common case that there is nothing to move.
1161 if (NumToMove)
1162 {
1163 memmove
1164 (
1165 (uint8_t*)_ElementStorage.GetAllocation() + (Index)* sizeof(ElementType),
1166 (uint8_t*)_ElementStorage.GetAllocation() + (Index + Count) * sizeof(ElementType),
1167 NumToMove * sizeof(ElementType)
1168 );
1169 }
1170 _ArrayNum -= Count;
1171
1172 if (bAllowShrinking)
1173 {
1174 ResizeShrink();
1175 }
1176 }
1177 }
1178
1179public:
1189 {
1190 RemoveAtImpl(Index, 1, true);
1191 }
1192
1201 template <typename CountType>
1202 ULANG_FORCEINLINE void RemoveAt(int32_t Index, CountType Count, bool bAllowShrinking = true)
1203 {
1204 static_assert(!TAreTypesEqual<CountType, bool>::Value, "TArrayG::RemoveAt: unexpected bool passed as the Count argument");
1205 RemoveAtImpl(Index, Count, bAllowShrinking);
1206 }
1207
1208private:
1209 void RemoveAtSwapImpl(int32_t Index, int32_t Count = 1, bool bAllowShrinking = true)
1210 {
1211 if (Count)
1212 {
1214 ULANG_ASSERTF((Count >= 0) & (Index >= 0) & (Index + Count <= _ArrayNum), "Cannot remove elements from array due to invalid parameters.");
1215
1217
1218 // Replace the elements in the hole created by the removal with elements from the end of the array, so the range of indices used by the array is contiguous.
1223 {
1224 memcpy(
1225 (uint8_t*)_ElementStorage.GetAllocation() + (Index)* sizeof(ElementType),
1226 (uint8_t*)_ElementStorage.GetAllocation() + (_ArrayNum - NumElementsToMoveIntoHole) * sizeof(ElementType),
1228 );
1229 }
1230 _ArrayNum -= Count;
1231
1232 if (bAllowShrinking)
1233 {
1234 ResizeShrink();
1235 }
1236 }
1237 }
1238
1239public:
1253 {
1254 RemoveAtSwapImpl(Index, 1, true);
1255 }
1256
1269 template <typename CountType>
1270 ULANG_FORCEINLINE void RemoveAtSwap(int32_t Index, CountType Count, bool bAllowShrinking = true)
1271 {
1272 static_assert(!TAreTypesEqual<CountType, bool>::Value, "TArrayG::RemoveAtSwap: unexpected bool passed as the Count argument");
1273 RemoveAtSwapImpl(Index, Count, bAllowShrinking);
1274 }
1275
1285 {
1287
1288 if (Index != IndexNone)
1289 {
1291 GetData()[Index] = NewItem;
1292 }
1293
1294 return Index;
1295 }
1296
1303 void Reset(int32_t NewSize = 0)
1304 {
1305 // If we have space to hold the excepted size, then don't reallocate
1306 if (NewSize <= _ArrayMax)
1307 {
1309 _ArrayNum = 0;
1310 }
1311 else
1312 {
1313 Empty(NewSize);
1314 }
1315 }
1316
1322 void Empty(int32_t Slack = 0)
1323 {
1325
1326 ULANG_ASSERTF(Slack >= 0, "Array slack must be positive.");
1327 _ArrayNum = 0;
1328
1329 if (_ArrayMax != Slack)
1330 {
1331 ResizeTo(Slack);
1332 }
1333 }
1334
1341 void SetNum(int32_t NewNum, bool bAllowShrinking = true)
1342 {
1343 if (NewNum > Num())
1344 {
1345 const int32_t Diff = NewNum - _ArrayNum;
1346 const int32_t Index = AddUninitialized(Diff);
1348 }
1349 else if (NewNum < Num())
1350 {
1351 RemoveAt(NewNum, Num() - NewNum, bAllowShrinking);
1352 }
1353 }
1354
1360 void SetNumZeroed(int32_t NewNum, bool bAllowShrinking = true)
1361 {
1362 if (NewNum > Num())
1363 {
1364 AddZeroed(NewNum - Num());
1365 }
1366 else if (NewNum < Num())
1367 {
1368 RemoveAt(NewNum, Num() - NewNum, bAllowShrinking);
1369 }
1370 }
1371
1377 void SetNumUninitialized(int32_t NewNum, bool bAllowShrinking = true)
1378 {
1379 if (NewNum > Num())
1380 {
1382 }
1383 else if (NewNum < Num())
1384 {
1385 RemoveAt(NewNum, Num() - NewNum, bAllowShrinking);
1386 }
1387 }
1388
1394 {
1395 ULANG_ASSERTF(NewNum <= Num() && NewNum >= 0, "Incorrect new array size.");
1396 _ArrayNum = NewNum;
1397 }
1398
1407 template <typename OtherElementAllocatorType, typename... OtherRawAllocatorArgsType>
1409 {
1410 ULANG_ASSERTF((void*)this != (void*)&Source, "Attempted to append array to itself.");
1411
1412 int32_t SourceCount = Source.Num();
1413
1414 // Do nothing if the source is empty.
1415 if (!SourceCount)
1416 {
1417 return;
1418 }
1419
1420 // Allocate memory for the new elements.
1423
1425 }
1426
1433 template <typename OtherElementAllocatorType, typename... OtherRawAllocatorArgsType>
1435 {
1436 ULANG_ASSERTF((void*)this != (void*)&Source, "Attempted to append array to itself.");
1437
1438 int32_t SourceCount = Source.Num();
1439
1440 // Do nothing if the source is empty.
1441 if (!SourceCount)
1442 {
1443 return;
1444 }
1445
1446 // Allocate memory for the new elements.
1449 Source._ArrayNum = 0;
1450
1452 }
1453
1462 {
1463 ULANG_ASSERTF(Ptr != nullptr || Count == 0, "Attempted to append invalid array.");
1464
1467 }
1468
1475 ULANG_FORCEINLINE void Append(std::initializer_list<ElementType> InitList)
1476 {
1477 int32_t Count = (int32_t)InitList.size();
1478
1481 }
1482
1492 {
1493 Append(Move(Other));
1494 return *this;
1495 }
1496
1504 {
1505 Append(Other);
1506 return *this;
1507 }
1508
1514 TArrayG& operator+=(std::initializer_list<ElementType> InitList)
1515 {
1517 return *this;
1518 }
1519
1526 template <typename... ArgsType>
1528 {
1529 const int32_t Index = AddUninitialized(1);
1530 new(GetData() + Index) ElementType(ForwardArg<ArgsType>(Args)...);
1531 return Index;
1532 }
1533
1540 template <typename... ArgsType>
1542 {
1543 const int32_t Index = AddUninitialized(1);
1544 ElementType* Ptr = GetData() + Index;
1545 new(Ptr) ElementType(ForwardArg<ArgsType>(Args)...);
1546 return *Ptr;
1547 }
1548
1555 template <typename... ArgsType>
1561
1569 template <typename... ArgsType>
1571 {
1573 ElementType* Ptr = GetData() + Index;
1574 new(Ptr) ElementType(ForwardArg<ArgsType>(Args)...);
1575 return *Ptr;
1576 }
1577
1588 {
1589 CheckAddress(&Item);
1590 return Emplace(uLang::MoveIfPossible(Item));
1591 }
1592
1601 {
1602 CheckAddress(&Item);
1603 return Emplace(Item);
1604 }
1605
1620
1629 {
1630 CheckAddress(&Item);
1631 return Emplace_GetRef(Item);
1632 }
1633
1647 {
1649 if (Count)
1650 {
1651 memset((uint8_t*)_ElementStorage.GetAllocation() + Index*sizeof(ElementType), 0, Count*sizeof(ElementType));
1652 }
1653 return Index;
1654 }
1655
1668 {
1669 const int32_t Index = AddUninitialized(1);
1670 ElementType* Ptr = GetData() + Index;
1671 memset(Ptr, 0, sizeof(ElementType));
1672 return *Ptr;
1673 }
1674
1689
1698 {
1699 const int32_t Index = AddUninitialized(1);
1700 ElementType* Ptr = GetData() + Index;
1702 return *Ptr;
1703 }
1704
1705private:
1706
1713 template <typename ArgsType>
1714 int32_t AddUniqueImpl(ArgsType&& Args)
1715 {
1716 int32_t Index;
1717 if (Find(Args, Index))
1718 {
1719 return Index;
1720 }
1721
1722 return Add(ForwardArg<ArgsType>(Args));
1723 }
1724
1725public:
1726
1737
1745 ULANG_FORCEINLINE int32_t AddUnique(const ElementType& Item) { return AddUniqueImpl(Item); }
1746
1754 {
1755 if (Number > _ArrayMax)
1756 {
1757 ResizeTo(Number);
1758 }
1759 }
1760
1767 void Init(const ElementType& Element, int32_t Number)
1768 {
1769 Empty(Number);
1770 for (int32_t Index = 0; Index < Number; ++Index)
1771 {
1772 new(*this) ElementType(Element);
1773 }
1774 }
1775
1785 {
1786 int32_t Index = Find(Item);
1787 if (Index == IndexNone)
1788 {
1789 return 0;
1790 }
1791
1792 auto* RemovePtr = GetData() + Index;
1793
1794 // Destruct items that match the specified Item.
1797
1798 // Update the array count
1799 --_ArrayNum;
1800
1801 // Removed one item
1802 return 1;
1803 }
1804
1813 template <typename OtherElementType>
1815 {
1816 CheckAddress(&Item);
1817
1818 // Element is non-const to preserve compatibility with existing code with a non-const operator==() member function
1819 return RemoveAll([&Item](ElementType& Element) { return Element == Item; });
1820 }
1821
1830 template <class PREDICATE_CLASS>
1832 {
1833 const int32_t OriginalNum = _ArrayNum;
1834 if (!OriginalNum)
1835 {
1836 return 0; // nothing to do, loop assumes one item so need to deal with this edge case here
1837 }
1838
1839 int32_t WriteIndex = 0;
1840 int32_t ReadIndex = 0;
1841 bool NotMatch = !Predicate(GetData()[ReadIndex]); // use a ! to guarantee it can't be anything other than zero or one
1842 do
1843 {
1844 int32_t RunStartIndex = ReadIndex++;
1845 while (ReadIndex < OriginalNum && NotMatch == !Predicate(GetData()[ReadIndex]))
1846 {
1847 ReadIndex++;
1848 }
1849 int32_t RunLength = ReadIndex - RunStartIndex;
1850 ULANG_ASSERTF(RunLength > 0, "RunLength must be positive here.");
1851 if (NotMatch)
1852 {
1853 // this was a non-matching run, we need to move it
1854 if (WriteIndex != RunStartIndex)
1855 {
1857 }
1858 WriteIndex += RunLength;
1859 }
1860 else
1861 {
1862 // this was a matching run, delete it
1864 }
1865 NotMatch = !NotMatch;
1866 } while (ReadIndex < OriginalNum);
1867
1868 _ArrayNum = WriteIndex;
1869 return OriginalNum - _ArrayNum;
1870 }
1871
1878 template <class PREDICATE_CLASS>
1879 void RemoveAllSwap(const PREDICATE_CLASS& Predicate, bool bAllowShrinking = true)
1880 {
1881 for (int32_t ItemIndex = 0; ItemIndex < Num();)
1882 {
1883 if (Predicate((*this)[ItemIndex]))
1884 {
1885 RemoveAtSwap(ItemIndex, 1, bAllowShrinking);
1886 }
1887 else
1888 {
1889 ++ItemIndex;
1890 }
1891 }
1892 }
1893
1903 int32_t RemoveSingleSwap(const ElementType& Item, bool bAllowShrinking = true)
1904 {
1905 int32_t Index = Find(Item);
1906 if (Index == IndexNone)
1907 {
1908 return 0;
1909 }
1910
1911 RemoveAtSwap(Index, 1, bAllowShrinking);
1912
1913 // Removed one item
1914 return 1;
1915 }
1916
1928 {
1929 CheckAddress(&Item);
1930
1931 const int32_t OriginalNum = _ArrayNum;
1932 for (int32_t Index = 0; Index < _ArrayNum; Index++)
1933 {
1934 if ((*this)[Index] == Item)
1935 {
1937 }
1938 }
1939 return OriginalNum - _ArrayNum;
1940 }
1941
1942public:
1943
1949 ULANG_FORCEINLINE const ElementType * begin() const { return GetData(); }
1951 ULANG_FORCEINLINE const ElementType * end() const { return GetData() + Num(); }
1952
1953public:
1954
1967
1978 template <class PredicateType>
1979 void Sort(const PredicateType& Predicate)
1980 {
1981 Algo::Sort( *this, TDereferenceWrapper<PredicateType>( Predicate ) );
1982 }
1983
1984 template <class PredicateType>
1985 void StableSort(const PredicateType& Predicate)
1986 {
1988 }
1989
1994 {
1995 ElementType* LastEntry = nullptr;
1996 int32_t ToIndex = 0;
1997 int32_t FromIndex = 0;
1998 while (FromIndex < Num())
1999 {
2000 ElementType ThisEntry = Move((*this)[FromIndex++]);
2001 if (!LastEntry || !(*LastEntry == ThisEntry))
2002 {
2003 LastEntry = &(*this)[ToIndex];
2004 (*this)[ToIndex++] = Move(ThisEntry);
2005 }
2006 }
2008 }
2009
2010private:
2011
2012 ULANG_FORCENOINLINE void ResizeGrow(int32_t OldNum)
2013 {
2014 _ArrayMax = _ElementStorage.CalculateSlackGrow(_ArrayNum, _ArrayMax, sizeof(ElementType));
2015 _ElementStorage.ResizeAllocation(OldNum, _ArrayMax, sizeof(ElementType));
2016 }
2017 ULANG_FORCENOINLINE void ResizeShrink()
2018 {
2019 const int32_t NewArrayMax = _ElementStorage.CalculateSlackShrink(_ArrayNum, _ArrayMax, sizeof(ElementType));
2020 if (NewArrayMax != _ArrayMax)
2021 {
2023 ULANG_ASSERTF(_ArrayMax >= _ArrayNum, "Attempted to shrink array to less than its count.");
2024 _ElementStorage.ResizeAllocation(_ArrayNum, _ArrayMax, sizeof(ElementType));
2025 }
2026 }
2027 ULANG_FORCENOINLINE void ResizeTo(int32_t NewMax)
2028 {
2029 if (NewMax)
2030 {
2031 NewMax = _ElementStorage.CalculateSlackReserve(NewMax, sizeof(ElementType));
2032 }
2033 if (NewMax != _ArrayMax)
2034 {
2035 _ArrayMax = NewMax;
2036 _ElementStorage.ResizeAllocation(_ArrayNum, _ArrayMax, sizeof(ElementType));
2037 }
2038 }
2039 ULANG_FORCENOINLINE void ResizeForCopy(int32_t NewMax, int32_t PrevMax)
2040 {
2041 if (NewMax)
2042 {
2043 NewMax = _ElementStorage.CalculateSlackReserve(NewMax, sizeof(ElementType));
2044 }
2045 if (NewMax != PrevMax)
2046 {
2047 _ElementStorage.ResizeAllocation(0, NewMax, sizeof(ElementType));
2048 }
2049 _ArrayMax = NewMax;
2050 }
2051
2052
2063 template <typename OtherElementType>
2064 void CopyToEmpty(const OtherElementType* OtherData, int32_t OtherNum, int32_t PrevMax, int32_t ExtraSlack)
2065 {
2066 ULANG_ASSERTF(ExtraSlack >= 0, "Array slack must be positive.");
2068 if (OtherNum || ExtraSlack || PrevMax)
2069 {
2070 ResizeForCopy(OtherNum + ExtraSlack, PrevMax);
2072 }
2073 else
2074 {
2075 _ArrayMax = 0;
2076 }
2077 }
2078
2079protected:
2080
2082 ElementAllocatorType::NeedsElementType,
2083 typename ElementAllocatorType::template ForElementType<ElementType>,
2084 typename ElementAllocatorType::ForAnyElementType
2085 >::Result;
2086
2090
2091};
2092
2094template<class ElementType>
2096
2098template<class ElementType>
2100
2101template <typename ElementType, typename ElementAllocatorType, typename... RawAllocatorArgsType>
2106
2107template <typename ElementType, typename ElementAllocatorType, typename... RawAllocatorArgsType>
2108struct TContainerTraits<TArrayG<ElementType, ElementAllocatorType, RawAllocatorArgsType...>> : public TContainerTraitsBase<TArrayG<ElementType, ElementAllocatorType, RawAllocatorArgsType...>>
2109{
2110 static_assert(TAllocatorTraits<ElementAllocatorType>::SupportsMove, "TArrayG no longer supports move-unaware allocators");
2112};
2113
2114template <typename ElementType, typename ElementAllocatorType, typename... RawAllocatorArgsType>
2115struct TIsContiguousContainer<TArrayG<ElementType, ElementAllocatorType, RawAllocatorArgsType...>>
2116{
2117 enum { Value = true };
2118};
2119
2120
2124template <typename T> struct TIsTArray { enum { Value = false }; };
2125
2126template <typename ElementType, typename ElementAllocatorType, typename... RawAllocatorArgsType> struct TIsTArray< TArrayG<ElementType, ElementAllocatorType, RawAllocatorArgsType...>> { enum { Value = true }; };
2127template <typename ElementType, typename ElementAllocatorType, typename... RawAllocatorArgsType> struct TIsTArray<const TArrayG<ElementType, ElementAllocatorType, RawAllocatorArgsType...>> { enum { Value = true }; };
2128template <typename ElementType, typename ElementAllocatorType, typename... RawAllocatorArgsType> struct TIsTArray< volatile TArrayG<ElementType, ElementAllocatorType, RawAllocatorArgsType...>> { enum { Value = true }; };
2129template <typename ElementType, typename ElementAllocatorType, typename... RawAllocatorArgsType> struct TIsTArray<const volatile TArrayG<ElementType, ElementAllocatorType, RawAllocatorArgsType...>> { enum { Value = true }; };
2130
2131template <typename T>
2133{
2134 uint32_t Result = 0;
2135 for (const T& Element : Array)
2136 {
2137 Result = HashCombineFast(Result, GetTypeHash(Element));
2138 }
2139 return Result;
2140}
2141}
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
FORCEINLINE uint32 ToIndex(FHairStrandsTiles::ETileType Type)
Definition HairStrandsData.h:93
#define ULANG_RESTRICT
Definition Common.h:207
#define ULANG_FORCEINLINE
Definition Common.h:188
#define ULANG_FORCENOINLINE
Definition Common.h:189
#define ULANG_ASSERTF(expr, format,...)
Definition Common.h:290
memcpy(InputBufferBase, BinkBlocksData, BinkBlocksSize)
Definition EnableIf.h:20
Definition Allocator.h:35
static ULANG_FORCEINLINE constexpr T Min(const T A, const T B)
Returns lower value in a generic way.
Definition MathUtils.h:26
Definition Array.h:51
ULANG_FORCEINLINE void Shrink()
Definition Array.h:562
ULANG_FORCEINLINE int32_t Emplace(ArgsType &&... Args)
Definition Array.h:1527
ULANG_FORCEINLINE ElementType & Last(int32_t IndexFromTheEnd=0)
Definition Array.h:537
ULANG_FORCEINLINE bool operator!=(const TArrayG &OtherArray) const
Definition Array.h:855
ULANG_FORCEINLINE int32_t Max() const
Definition Array.h:413
ULANG_FORCEINLINE const ElementType * begin() const
Definition Array.h:1949
ElementType & AddDefaulted_GetRef()
Definition Array.h:1697
void InsertDefaulted(int32_t Index, int32_t Count=1)
Definition Array.h:957
ULANG_FORCEINLINE const ElementType * FindByPredicate(Predicate Pred) const
Definition Array.h:757
TArrayG(std::initializer_list< OtherElementType > InitList, RawAllocatorArgsType &&... RawAllocatorArgs)
Definition Array.h:118
int32_t Remove(const OtherElementType &Item)
Definition Array.h:1814
void SetNumUninitialized(int32_t NewNum, bool bAllowShrinking=true)
Definition Array.h:1377
ElementType & Insert_GetRef(ElementType &&Item, int32_t Index)
Definition Array.h:1117
ULANG_FORCEINLINE const ElementType * GetData() const
Definition Array.h:323
void RemoveSuccessiveDuplicates()
Definition Array.h:1993
InElementType ElementType
Definition Array.h:57
void SetNum(int32_t NewNum, bool bAllowShrinking=true)
Definition Array.h:1341
ULANG_FORCEINLINE void Append(std::initializer_list< ElementType > InitList)
Definition Array.h:1475
int32_t Insert(const TArrayG< ElementType, OtherElementAllocatorType, OtherRawAllocatorArgsType... > &Items, const int32_t InIndex)
Definition Array.h:1004
int32_t RemoveSwap(const ElementType &Item)
Definition Array.h:1927
typename TChooseClass< ElementAllocatorType::NeedsElementType, typename ElementAllocatorType::template ForElementType< ElementType >, typename ElementAllocatorType::ForAnyElementType >::Result ElementStorageType
Definition Array.h:2085
ULANG_FORCEINLINE TArrayG(int32_t Count, const ElementType &Value=ElementType(), RawAllocatorArgsType &&... RawAllocatorArgs)
Definition Array.h:93
ElementType & AddZeroed_GetRef()
Definition Array.h:1667
ULANG_FORCEINLINE void EmplaceAt(int32_t Index, ArgsType &&... Args)
Definition Array.h:1556
ElementType & InsertZeroed_GetRef(int32_t Index)
Definition Array.h:941
ULANG_FORCEINLINE TArrayG(TArrayG< ElementType, OtherElementAllocatorType, OtherRawAllocatorArgsType... > &&Other)
Definition Array.h:282
void SetNumZeroed(int32_t NewNum, bool bAllowShrinking=true)
Definition Array.h:1360
TArrayG & operator+=(TArrayG &&Other)
Definition Array.h:1491
ULANG_FORCEINLINE const ElementType * FindByKey(const KeyType &Key) const
Definition Array.h:722
void SetNumUnsafeInternal(int32_t NewNum)
Definition Array.h:1393
void Empty(int32_t Slack=0)
Definition Array.h:1322
ULANG_FORCEINLINE TArrayG(const TArrayG< OtherElementType, OtherElementAllocatorType, OtherRawAllocatorArgsType... > &Other, RawAllocatorArgsType &&... RawAllocatorArgs)
Definition Array.h:129
ULANG_FORCEINLINE const ElementType & Top() const
Definition Array.h:526
TArrayG & operator=(TArrayG &&Other)
Definition Array.h:292
ElementType * FindByKey(const KeyType &Key)
Definition Array.h:736
TArrayG & operator=(const TArrayG &Other)
Definition Array.h:165
ULANG_FORCEINLINE bool ContainsByPredicate(Predicate Pred) const
Definition Array.h:831
ULANG_FORCEINLINE bool Find(const ElementType &Item, int32_t &Index) const
Definition Array.h:579
ULANG_FORCEINLINE const ElementType * end() const
Definition Array.h:1951
ULANG_FORCEINLINE int32_t Add(const ElementType &Item)
Definition Array.h:1600
ULANG_FORCEINLINE uint32_t GetTypeSize() const
Definition Array.h:333
ULANG_FORCEINLINE ElementType & EmplaceAt_GetRef(int32_t Index, ArgsType &&... Args)
Definition Array.h:1570
ULANG_FORCEINLINE void CheckAddress(void const *Addr) const
Definition Array.h:1064
ULANG_FORCEINLINE TArrayG(const ElementType *Ptr, int32_t Count, RawAllocatorArgsType &&... RawAllocatorArgs)
Definition Array.h:85
ULANG_FORCEINLINE ElementType & Add_GetRef(const ElementType &Item)
Definition Array.h:1628
TArrayG FilterByPredicate(Predicate Pred) const
Definition Array.h:791
ULANG_FORCEINLINE void RemoveAt(int32_t Index)
Definition Array.h:1188
int32_t Find(const ElementType &Item) const
Definition Array.h:592
void Sort(const PredicateType &Predicate)
Definition Array.h:1979
~TArrayG()
Definition Array.h:303
void RemoveAllSwap(const PREDICATE_CLASS &Predicate, bool bAllowShrinking=true)
Definition Array.h:1879
ULANG_FORCEINLINE TArrayG(const TArrayG &Other, int32_t ExtraSlack)
Definition Array.h:153
ElementStorageType _ElementStorage
Definition Array.h:2087
int32_t Replace(const ElementType &OldItem, const ElementType &NewItem)
Definition Array.h:1284
void Append(const ElementType *Ptr, int32_t Count)
Definition Array.h:1461
ULANG_FORCEINLINE int32_t AddUninitialized(int32_t Count=1)
Definition Array.h:870
ULANG_FORCEINLINE ElementType * begin()
Definition Array.h:1948
void InsertZeroed(int32_t Index, int32_t Count=1)
Definition Array.h:921
int32_t AddZeroed(int32_t Count=1)
Definition Array.h:1646
ULANG_FORCEINLINE void Push(ElementType &&Item)
Definition Array.h:489
int32_t RemoveSingleSwap(const ElementType &Item, bool bAllowShrinking=true)
Definition Array.h:1903
int32_t Insert(const ElementType *Ptr, int32_t Count, int32_t Index)
Definition Array.h:1046
ULANG_FORCEINLINE int32_t FindLastByPredicate(Predicate Pred) const
Definition Array.h:667
void Reset(int32_t NewSize=0)
Definition Array.h:1303
void Init(const ElementType &Element, int32_t Number)
Definition Array.h:1767
int32_t _ArrayMax
Definition Array.h:2089
ULANG_FORCEINLINE void Push(const ElementType &Item)
Definition Array.h:502
ULANG_FORCEINLINE ElementType & Add_GetRef(ElementType &&Item)
Definition Array.h:1615
ULANG_FORCEINLINE bool IsEmpty() const
Definition Array.h:430
ULANG_FORCEINLINE int32_t AddUnique(const ElementType &Item)
Definition Array.h:1745
ULANG_FORCEINLINE bool IsFilled() const
Definition Array.h:441
ULANG_FORCEINLINE TArrayG(RawAllocatorArgsType &&... RawAllocatorArgs)
Definition Array.h:63
ULANG_FORCEINLINE ElementType * GetData()
Definition Array.h:313
ULANG_FORCEINLINE const ElementType & operator[](int32_t Index) const
Definition Array.h:464
ULANG_FORCEINLINE int32_t GetSlack() const
Definition Array.h:355
void StableSort(const PredicateType &Predicate)
Definition Array.h:1985
int32_t FindLast(const ElementType &Item) const
Definition Array.h:625
ULANG_FORCEINLINE void RemoveAt(int32_t Index, CountType Count, bool bAllowShrinking=true)
Definition Array.h:1202
ElementType & Insert_GetRef(const ElementType &Item, int32_t Index)
Definition Array.h:1137
int32_t Insert(ElementType &&Item, int32_t Index)
Definition Array.h:1078
ULANG_FORCEINLINE void CheckInvariants() const
Definition Array.h:364
ULANG_FORCEINLINE void RemoveAtSwap(int32_t Index)
Definition Array.h:1252
int32_t RemoveSingle(const ElementType &Item)
Definition Array.h:1784
int32_t Insert(std::initializer_list< ElementType > InitList, const int32_t InIndex)
Definition Array.h:986
ULANG_FORCEINLINE TArrayG(const TArrayG &Other)
Definition Array.h:140
void Append(const TArrayG< ElementType, OtherElementAllocatorType, OtherRawAllocatorArgsType... > &Source)
Definition Array.h:1408
int32_t Insert(TArrayG< ElementType, OtherElementAllocatorType, OtherRawAllocatorArgsType... > &&Items, const int32_t InIndex)
Definition Array.h:1024
TArrayG(TArrayG &&Other, int32_t ExtraSlack)
Definition Array.h:267
ULANG_FORCEINLINE const ElementType & Last(int32_t IndexFromTheEnd=0) const
Definition Array.h:551
ULANG_FORCEINLINE ElementType * end()
Definition Array.h:1950
bool Contains(const ComparisonType &Item) const
Definition Array.h:811
int32_t _ArrayNum
Definition Array.h:2088
ULANG_FORCEINLINE ElementType & Top()
Definition Array.h:513
ULANG_FORCEINLINE TArrayG(const typename ElementAllocatorType::RawAllocatorType &RawAllocator)
Definition Array.h:72
TArrayG & operator+=(const TArrayG &Other)
Definition Array.h:1503
TArrayG(std::initializer_list< InElementType > InitList, RawAllocatorArgsType &&... RawAllocatorArgs)
Definition Array.h:107
ULANG_FORCEINLINE ElementType Pop(bool bAllowShrinking=true)
Definition Array.h:476
TArrayG & operator+=(std::initializer_list< ElementType > InitList)
Definition Array.h:1514
ULANG_FORCEINLINE ElementType & Emplace_GetRef(ArgsType &&... Args)
Definition Array.h:1541
int32_t AddDefaulted(int32_t Count=1)
Definition Array.h:1683
ULANG_FORCEINLINE int32_t AddUnique(ElementType &&Item)
Definition Array.h:1736
bool operator==(const TArrayG &OtherArray) const
Definition Array.h:842
ElementType & InsertDefaulted_GetRef(int32_t Index)
Definition Array.h:971
ULANG_FORCEINLINE bool FindLast(const ElementType &Item, int32_t &Index) const
Definition Array.h:613
ULANG_FORCEINLINE TArrayG(TArrayG &&Other)
Definition Array.h:255
ULANG_FORCEINLINE const ElementAllocatorType::RawAllocatorType & GetRawAllocator() const
Definition Array.h:419
InElementAllocatorType ElementAllocatorType
Definition Array.h:58
int32_t IndexOfByPredicate(Predicate Pred) const
Definition Array.h:700
void Append(TArrayG< ElementType, OtherElementAllocatorType, OtherRawAllocatorArgsType... > &&Source)
Definition Array.h:1434
int32_t FindLastByPredicate(Predicate Pred, int32_t Count) const
Definition Array.h:646
ULANG_FORCEINLINE void RangeCheck(int32_t Index) const
Definition Array.h:374
ULANG_FORCEINLINE void Reserve(int32_t Number)
Definition Array.h:1753
ElementType * FindByPredicate(Predicate Pred)
Definition Array.h:769
ULANG_FORCEINLINE void RemoveAtSwap(int32_t Index, CountType Count, bool bAllowShrinking=true)
Definition Array.h:1270
ULANG_FORCEINLINE uint32_t GetAllocatedSize(void) const
Definition Array.h:345
int32_t Insert(const ElementType &Item, int32_t Index)
Definition Array.h:1097
ULANG_FORCEINLINE int32_t Add(ElementType &&Item)
Definition Array.h:1587
void InsertUninitialized(int32_t Index, int32_t Count=1)
Definition Array.h:895
int32_t IndexOfByKey(const KeyType &Key) const
Definition Array.h:680
ULANG_FORCEINLINE bool IsValidIndex(int32_t Index) const
Definition Array.h:391
ULANG_FORCEINLINE ElementType & operator[](int32_t Index)
Definition Array.h:451
int32_t RemoveAll(const PREDICATE_CLASS &Predicate)
Definition Array.h:1831
void Sort()
Definition Array.h:1963
ULANG_FORCEINLINE int32_t Num() const
Definition Array.h:402
Definition Conditionals.h:116
Definition Conditionals.h:95
Definition OverriddenPropertySet.cpp:45
ULANG_FORCEINLINE void StableSort(RangeType &&Range)
Definition StableSort.h:125
ULANG_FORCEINLINE void Sort(RangeType &&Range)
Definition Sort.h:18
Definition VVMEngineEnvironment.h:23
ULANG_FORCEINLINE TRemoveReference< T >::Type && MoveIfPossible(T &&Obj)
Definition References.h:104
constexpr uint32_t HashCombineFast(uint32_t A, uint32_t B)
Definition HashTraits.h:40
@ IndexNone
Definition Common.h:381
ULANG_FORCEINLINE TEnableIf< TTypeTraits< ElementType >::IsBytewiseComparable, bool >::Type CompareElements(const ElementType *A, const ElementType *B, int32_t Count)
Definition MemoryOps.h:182
ULANG_FORCEINLINE TEnableIf<!TIsTriviallyDestructible< ElementType >::Value >::Type DestructElements(ElementType *Element, int32_t Count)
Definition MemoryOps.h:91
ULANG_FORCEINLINE T && ForwardArg(typename TRemoveReference< T >::Type &Obj)
Definition References.h:115
ULANG_FORCEINLINE TRemoveReference< T >::Type && Move(T &&Obj)
Definition References.h:86
ULANG_FORCEINLINE uint32_t GetTypeHash(const TArray< T > Array)
Definition Array.h:2132
U16 Index
Definition radfft.cpp:71
typename FromArrayType::ElementType FromElementType
Definition Array.h:22
typename ToArrayType::ElementType ToElementType
Definition Array.h:23
typename ToArrayType::ElementAllocatorType ToAllocatorType
Definition Array.h:21
typename FromArrayType::ElementAllocatorType FromAllocatorType
Definition Array.h:20
Definition Allocator.h:238
Definition TypeTraits.h:36
@ Value
Definition TypeTraits.h:37
Definition TypeTraits.h:451
@ MoveWillEmptyContainer
Definition TypeTraits.h:453
Definition TypeTraits.h:456
Definition Sorting.h:82
Definition TypeTraits.h:473
Definition TypeTraits.h:263
@ Value
Definition TypeTraits.h:264
Definition Array.h:2124
@ Value
Definition Array.h:2124
Definition TypeTraits.h:325
Definition Sorting.h:36