UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
SparseSet.h.inl
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#ifndef UE_TSPARSE_SET
4#error "SparseSet.h.inl should only be included after defining UE_TSPARSE_SET"
5#endif
6
12#include "ContainersFwd.h"
15#include "Misc/StructBuilder.h"
18#include "Templates/Function.h"
20#include "Templates/Sorting.h"
21#include "Templates/TypeHash.h"
24#include <initializer_list>
25#include <type_traits>
26
27template <typename AllocatorType>
29
30#define TSETPRIVATEFRIEND PREPROCESSOR_JOIN(UE_TSPARSE_SET, PrivateFriend)
31
47template<
48 typename InElementType,
49 typename KeyFuncs /*= DefaultKeyFuncs<ElementType>*/,
50 typename Allocator /*= FDefaultSparseSetAllocator*/
51 >
53{
54public:
56 typedef KeyFuncs KeyFuncsType;
58
59 using SizeType = typename Allocator::SparseArrayAllocator::ElementAllocator::SizeType;
60
61 static_assert(std::is_same_v<SizeType, int32>, "UE_TSPARSE_SET currently only supports 32-bit allocators");
62
63private:
64 using USizeType = std::make_unsigned_t<SizeType>;
65
66 template <typename>
67 friend class TScriptSparseSet;
68
69 typedef typename KeyFuncs::KeyInitType KeyInitType;
70 typedef typename KeyFuncs::ElementInitType ElementInitType;
71
73
74public:
76 [[nodiscard]] UE_FORCEINLINE_HINT constexpr UE_TSPARSE_SET() = default;
77
78 [[nodiscard]] explicit consteval UE_TSPARSE_SET(EConstEval)
79 : Elements(ConstEval)
81 {
82 }
83
89
94
99
102 {
103 UE_STATIC_ASSERT_WARN(TIsTriviallyRelocatable_V<InElementType>, "TSet can only be used with trivially relocatable types");
104 HashSize = 0;
105 }
106
108 // Start - intrusive TOptional<UE_TSPARSE_SET> state //
110 constexpr static bool bHasIntrusiveUnsetOptionalState = true;
112
114 : Elements(Tag)
115 {
116 }
118 {
119 return Elements == Tag;
120 }
122 // End - intrusive TOptional<UE_TSPARSE_SET> state //
124
127 {
128 if (this != &Copy)
129 {
130 UE::Core::Private::CopyHash(Hash, HashSize, Copy.Hash, Copy.HashSize);
131
132 Elements = Copy.Elements;
133 }
134 return *this;
135 }
136
137private:
138 template <typename SetType>
139 static inline void Move(SetType& ToSet, SetType& FromSet)
140 {
141 ToSet.Elements = (ElementArrayType&&)FromSet.Elements;
142
143 ToSet.Hash.MoveToEmpty(FromSet.Hash);
144
145 ToSet .HashSize = FromSet.HashSize;
146 FromSet.HashSize = 0;
147 }
148
149public:
151 [[nodiscard]] UE_TSPARSE_SET(std::initializer_list<ElementType> InitList)
152 : HashSize(0)
153 {
155 }
156
159 : HashSize(0)
160 {
161 this->Move(*this, Other);
162 }
163
166 {
167 if (this != &Other)
168 {
169 this->Move(*this, Other);
170 }
171
172 return *this;
173 }
174
176 template<typename OtherAllocator>
182
184 template<typename OtherAllocator>
190
192 template<typename OtherAllocator>
199
201 template<typename OtherAllocator>
208
210 UE_TSPARSE_SET& operator=(std::initializer_list<ElementType> InitList)
211 {
212 Reset();
214 return *this;
215 }
216
222 {
223 // Empty the elements array, and reallocate it for the expected number of elements.
224 const int32 DesiredHashSize = Allocator::GetNumberOfHashBuckets(ExpectedNumElements);
226
227 if (!ShouldDoRehash)
228 {
229 // If the hash was already the desired size, clear the references to the elements that have now been removed.
230 UnhashElements();
231 }
232
233 Elements.Empty(ExpectedNumElements);
234
235 // Resize the hash to the desired size for the expected number of elements.
236 if (ShouldDoRehash)
237 {
238 HashSize = DesiredHashSize;
239 Rehash();
240 }
241 }
242
244 void Reset()
245 {
246 if (Num() == 0)
247 {
248 return;
249 }
250
251 // Reset the elements array.
252 UnhashElements();
253 Elements.Reset();
254 }
255
257 inline void Shrink()
258 {
259 Elements.Shrink();
260 Relax();
261 }
262
264 inline void Compact()
265 {
266 if (Elements.Compact())
267 {
268 HashSize = Allocator::GetNumberOfHashBuckets(Elements.Num());
269 Rehash();
270 }
271 }
272
274 inline void CompactStable()
275 {
276 if (Elements.CompactStable())
277 {
278 HashSize = Allocator::GetNumberOfHashBuckets(Elements.Num());
279 Rehash();
280 }
281 }
282
284 inline void Reserve(int32 Number)
285 {
286 // makes sense only when Number > Elements.Num() since TSparseArray::Reserve
287 // does any work only if that's the case
288 if ((USizeType)Number > (USizeType)Elements.Num())
289 {
290 // Trap negative reserves
291 if (Number < 0)
292 {
293 UE::Core::Private::OnInvalidSetNum((unsigned long long)Number);
294 }
295
296 // Preallocates memory for array of elements
297 Elements.Reserve(Number);
298
299 // Calculate the corresponding hash size for the specified number of elements.
300 const int32 NewHashSize = Allocator::GetNumberOfHashBuckets(Number);
301
302 // If the hash hasn't been created yet, or is smaller than the corresponding hash size, rehash
303 // to force a preallocation of the hash table
304 if(!HashSize || HashSize < NewHashSize)
305 {
306 HashSize = NewHashSize;
307 Rehash();
308 }
309 }
310 }
311
314 {
315 ConditionalRehash(Elements.Num(), EAllowShrinking::Yes);
316 }
317
324 {
325 return Elements.GetAllocatedSize() + Hash.GetAllocatedSize(HashSize, sizeof(FSetElementId));
326 }
327
329 inline void CountBytes(FArchive& Ar) const
330 {
331 Elements.CountBytes(Ar);
332 Ar.CountBytes(HashSize * sizeof(int32),HashSize * sizeof(FSetElementId));
333 }
334
341 [[nodiscard]] bool IsEmpty() const
342 {
343 return Elements.IsEmpty();
344 }
345
348 {
349 return Elements.Num();
350 }
351
354 {
355 return Elements.Max();
356 }
357
360 {
361 return Elements.GetMaxIndex();
362 }
363
369 [[nodiscard]] inline bool IsValidId(FSetElementId Id) const
370 {
371 SizeType Index = Id.AsInteger();
372 return Index != INDEX_NONE &&
373 Index >= 0 &&
374 Index < Elements.GetMaxIndex() &&
375 Elements.IsAllocated(Index);
376 }
377
380 {
381 return Elements[Id.AsInteger()].Value;
382 }
383
386 {
387 return Elements[Id.AsInteger()].Value;
388 }
389
392 {
393 return Elements[Id.AsInteger()].Value;
394 }
395
398 {
399 return Elements[Id.AsInteger()].Value;
400 }
401
417
426 {
427 return FindOrAddByHash(KeyFuncs::GetKeyHash(KeyFuncs::GetSetKey(InElement)), InElement, bIsAlreadyInSetPtr);
428 }
430 {
431 return FindOrAddByHash(KeyFuncs::GetKeyHash(KeyFuncs::GetSetKey(InElement)), MoveTempIfPossible(InElement), bIsAlreadyInSetPtr);
432 }
433
451
461 template <typename ElementReferenceType>
463 {
464 SizeType ExistingIndex = FindIndexByHash(KeyHash, KeyFuncs::GetSetKey(InElement));
467 {
469 }
470 if (bIsAlreadyInSet)
471 {
472 return Elements[ExistingIndex].Value;
473 }
474
475 // Create a new element.
478 RehashOrLink(KeyHash, Element, ElementAllocation.Index);
479 return Element.Value;
480 }
481
482private:
483 bool TryReplaceExisting(uint32 KeyHash, SetElementType& Element, SizeType& InOutElementIndex, bool* bIsAlreadyInSetPtr)
484 {
485 bool bIsAlreadyInSet = false;
486 if constexpr (!KeyFuncs::bAllowDuplicateKeys)
487 {
488 // If the set doesn't allow duplicate keys, check for an existing element with the same key as the element being added.
489
490 // Don't bother searching for a duplicate if this is the first element we're adding
491 if (Elements.Num() != 1)
492 {
493 SizeType ExistingIndex = FindIndexByHash(KeyHash, KeyFuncs::GetSetKey(Element.Value));
495 if (bIsAlreadyInSet)
496 {
497 // If there's an existing element with the same key as the new element, replace the existing element with the new element.
498 MoveByRelocate(Elements[ExistingIndex].Value, Element.Value);
499
500 // Then remove the new element.
502
503 // Then point the return value at the replaced element.
505 }
506 }
507 }
509 {
511 }
512 return bIsAlreadyInSet;
513 }
514
515 inline void RehashOrLink(uint32 KeyHash, SetElementType& Element, SizeType ElementIndex)
516 {
517 // Check if the hash needs to be resized.
518 if (!ConditionalRehash(Elements.Num(), EAllowShrinking::No))
519 {
520 // If the rehash didn't add the new element to the hash, add it.
521 LinkElement(ElementIndex, Element, KeyHash);
522 }
523 }
524
525public:
533 template <typename ArgType = ElementType>
535 {
536 // Create a new element.
539
541
542 uint32 KeyHash = KeyFuncs::GetKeyHash(KeyFuncs::GetSetKey(Element.Value));
543 if (!TryReplaceExisting(KeyHash, Element, NewHashIndex, bIsAlreadyInSetPtr))
544 {
545 RehashOrLink(KeyHash, Element, NewHashIndex);
546 }
548 }
549
557 template <typename... ArgTypes>
559 {
560 // Create a new element.
563
565 const uint32 KeyHash = KeyFuncs::GetKeyHash(KeyFuncs::GetSetKey(Element.Value));
566
567 bool bAlreadyInSet = false;
568 if (!TryReplaceExisting(KeyHash, Element, NewHashIndex, &bAlreadyInSet))
569 {
570 RehashOrLink(KeyHash, Element, NewHashIndex);
571 }
572
574 }
575
585 template <typename ArgType = ElementType>
587 {
588 // Create a new element.
591
593
594 if (!TryReplaceExisting(KeyHash, Element, NewHashIndex, bIsAlreadyInSetPtr))
595 {
596 RehashOrLink(KeyHash, Element, NewHashIndex);
597 }
599 }
600
610 template <typename... ArgTypes>
612 {
613 // Create a new element.
616
618 bool bAlreadyInSet = false;
619 if (!TryReplaceExisting(KeyHash, Element, NewHashIndex, &bAlreadyInSet))
620 {
621 RehashOrLink(KeyHash, Element, NewHashIndex);
622 }
624 }
625
627 {
628 Reserve(Elements.Num() + InElements.Num());
629 for (const ElementType& Element : InElements)
630 {
631 Add(Element);
632 }
633 }
634
635 template<typename ArrayAllocator>
637 {
638 Reserve(Elements.Num() + InElements.Num());
639 for (ElementType& Element : InElements)
640 {
641 Add(MoveTempIfPossible(Element));
642 }
643 InElements.Reset();
644 }
645
650 template<typename OtherAllocator>
652 {
653 Reserve(Elements.Num() + OtherSet.Num());
654 for (const ElementType& Element : OtherSet)
655 {
656 Add(Element);
657 }
658 }
659
660 template<typename OtherAllocator>
662 {
663 Reserve(Elements.Num() + OtherSet.Num());
664 for (ElementType& Element : OtherSet)
665 {
666 Add(MoveTempIfPossible(Element));
667 }
668 OtherSet.Reset();
669 }
670
671 void Append(std::initializer_list<ElementType> InitList)
672 {
673 Reserve(Elements.Num() + (int32)InitList.size());
674 for (const ElementType& Element : InitList)
675 {
676 Add(Element);
677 }
678 }
679
680private:
681 void RemoveByIndex(SizeType ElementIndex)
682 {
683 checkf(Elements.IsValidIndex(ElementIndex), TEXT("Invalid ElementIndex passed to UE_TSPARSE_SET::RemoveByIndex"));
684
685 const SetElementType& ElementBeingRemoved = Elements[ElementIndex];
686
687 // Remove the element from the hash.
688 FSetElementId* HashPtr = Hash.GetAllocation();
690 for (;;)
691 {
692 SizeType NextElementIndex = NextElementIndexIter->AsInteger();
693 checkf(NextElementIndex != INDEX_NONE, TEXT("Corrupt hash"));
694
695 if (NextElementIndex == ElementIndex)
696 {
698 break;
699 }
700
701 NextElementIndexIter = &Elements[NextElementIndex].HashNextId;
702 }
703
704 // Remove the element from the elements array.
705 Elements.RemoveAt(ElementIndex);
706 }
707
708public:
713 void Remove(FSetElementId ElementId)
714 {
715 RemoveByIndex(ElementId.AsInteger());
716 }
717
723 {
724 Remove(ElementId);
726 }
727
728private:
734 template <typename ComparableKey>
735 [[nodiscard]] SizeType FindIndexByHash(uint32 KeyHash, const ComparableKey& Key) const
736 {
737 if (Elements.Num() == 0)
738 {
739 return INDEX_NONE;
740 }
741
742 FSetElementId* HashPtr = Hash.GetAllocation();
743 SizeType ElementIndex = HashPtr[KeyHash & (HashSize - 1)].AsInteger();
744 for (;;)
745 {
746 if (ElementIndex == INDEX_NONE)
747 {
748 return INDEX_NONE;
749 }
750
751 if (KeyFuncs::Matches(KeyFuncs::GetSetKey(Elements[ElementIndex].Value), Key))
752 {
753 // Return the first match, regardless of whether the set has multiple matches for the key or not.
754 return ElementIndex;
755 }
756
757 ElementIndex = Elements[ElementIndex].HashNextId.AsInteger();
758 }
759 }
760
761public:
768 {
769 // The goal of this function is to be fast, and so the implementation may be improved at any time even if it gives different results.
770
771 int32 Result = Elements.FindArbitraryElementIndex();
772 return (Result != INDEX_NONE) ? &Elements[Result].Value : nullptr;
773 }
775 {
776 return const_cast<UE_TSPARSE_SET*>(this)->FindArbitraryElement();
777 }
778
784 [[nodiscard]] FSetElementId FindId(KeyInitType Key) const
785 {
786 return FSetElementId::FromInteger(FindIndexByHash(KeyFuncs::GetKeyHash(Key), Key));
787 }
788
794 template<typename ComparableKey>
796 {
798 // Disable deprecations warnings to stop warnings being thrown by our check macro.
799 checkSlow(KeyHash == KeyFuncs::GetKeyHash(Key));
801
802 return FSetElementId::FromInteger(FindIndexByHash(KeyHash, Key));
803 }
804
810 [[nodiscard]] inline ElementType* Find(KeyInitType Key)
811 {
812 SizeType ElementIndex = FindIndexByHash(KeyFuncs::GetKeyHash(Key), Key);
813 if (ElementIndex != INDEX_NONE)
814 {
815 return &Elements[ElementIndex].Value;
816 }
817 else
818 {
819 return nullptr;
820 }
821 }
822
828 [[nodiscard]] UE_FORCEINLINE_HINT const ElementType* Find(KeyInitType Key) const
829 {
830 return const_cast<UE_TSPARSE_SET*>(this)->Find(Key);
831 }
832
838 template<typename ComparableKey>
840 {
841 SizeType ElementIndex = FindIndexByHash(KeyHash, Key);
842 if (ElementIndex != INDEX_NONE)
843 {
844 return &Elements[ElementIndex].Value;
845 }
846 else
847 {
848 return nullptr;
849 }
850 }
851
852 template<typename ComparableKey>
853 [[nodiscard]] const ElementType* FindByHash(uint32 KeyHash, const ComparableKey& Key) const
854 {
855 return const_cast<UE_TSPARSE_SET*>(this)->FindByHash(KeyHash, Key);
856 }
857
858private:
859 template<typename ComparableKey>
860 inline int32 RemoveImpl(uint32 KeyHash, const ComparableKey& Key)
861 {
863
864 FSetElementId* NextElementId = &GetTypedHash(KeyHash);
865 while (NextElementId->IsValidId())
866 {
867 const int32 ElementIndex = NextElementId->AsInteger();
868 SetElementType& Element = Elements[ElementIndex];
869
870 if (KeyFuncs::Matches(KeyFuncs::GetSetKey(Element.Value), Key))
871 {
872 // This element matches the key, remove it from the set. Note that Remove sets *NextElementId to point to the next
873 // element after the removed element in the hash bucket.
874 RemoveByIndex(ElementIndex);
876
877 if constexpr (!KeyFuncs::bAllowDuplicateKeys)
878 {
879 // If the hash disallows duplicate keys, we're done removing after the first matched key.
880 break;
881 }
882 }
883 else
884 {
885 NextElementId = &Element.HashNextId;
886 }
887 }
888
889 return NumRemovedElements;
890 }
891
892public:
898 int32 Remove(KeyInitType Key)
899 {
900 if (Elements.Num())
901 {
902 return RemoveImpl(KeyFuncs::GetKeyHash(Key), Key);
903 }
904
905 return 0;
906 }
907
912 int32 RemoveStable(KeyInitType Key)
913 {
914 int32 Result = 0;
915
916 if (Elements.Num())
917 {
918 Result = RemoveImpl(KeyFuncs::GetKeyHash(Key), Key);
920 }
921
922 return Result;
923 }
924
932 template<typename ComparableKey>
934 {
936 // Disable deprecations warnings to stop warnings being thrown by our check macro.
937 checkSlow(KeyHash == KeyFuncs::GetKeyHash(Key));
939
940 if (Elements.Num())
941 {
942 return RemoveImpl(KeyHash, Key);
943 }
944
945 return 0;
946 }
947
953 [[nodiscard]] UE_FORCEINLINE_HINT bool Contains(KeyInitType Key) const
954 {
955 return FindIndexByHash(KeyFuncs::GetKeyHash(Key), Key) != INDEX_NONE;
956 }
957
963 template<typename ComparableKey>
964 [[nodiscard]] inline bool ContainsByHash(uint32 KeyHash, const ComparableKey& Key) const
965 {
967 // Disable deprecations warnings to stop warnings being thrown by our check macro.
968 checkSlow(KeyHash == KeyFuncs::GetKeyHash(Key));
970
971 return FindIndexByHash(KeyHash, Key) != INDEX_NONE;
972 }
973
977 template <typename PREDICATE_CLASS>
978 void Sort( const PREDICATE_CLASS& Predicate )
979 {
980 // Sort the elements according to the provided comparison class.
981 Elements.Sort( FElementCompareClass< PREDICATE_CLASS >( Predicate ) );
982
983 // Rehash.
984 Rehash();
985 }
986
990 template <typename PREDICATE_CLASS>
991 void StableSort(const PREDICATE_CLASS& Predicate)
992 {
993 // Sort the elements according to the provided comparison class.
995
996 // Rehash.
997 Rehash();
998 }
999
1006 {
1007 Elements.SortFreeList();
1008 }
1009
1015 {
1016 Ar.Logf( TEXT("UE_TSPARSE_SET: %i elements, %i hash slots"), Elements.Num(), HashSize );
1017 for (int32 HashIndex = 0, LocalHashSize = HashSize; HashIndex < LocalHashSize; ++HashIndex)
1018 {
1019 // Count the number of elements in this hash bucket.
1021 for(FSetElementId ElementId = GetTypedHash(HashIndex);
1022 ElementId.IsValidId();
1023 ElementId = Elements[ElementId.AsInteger()].HashNextId)
1024 {
1026 }
1027
1028 Ar.Logf(TEXT(" Hash[%i] = %i"),HashIndex,NumElementsInBucket);
1029 }
1030 }
1031
1032 [[nodiscard]] bool VerifyHashElementsKey(KeyInitType Key) const
1033 {
1034 bool bResult=true;
1035 if (Elements.Num())
1036 {
1037 // iterate over all elements for the hash entry of the given key
1038 // and verify that the ids are valid
1039 FSetElementId ElementId = GetTypedHash(KeyFuncs::GetKeyHash(Key));
1040 while( ElementId.IsValidId() )
1041 {
1042 if( !IsValidId(ElementId) )
1043 {
1044 bResult=false;
1045 break;
1046 }
1047 ElementId = Elements[ElementId.AsInteger()].HashNextId;
1048 }
1049 }
1050 return bResult;
1051 }
1052
1054 {
1055 for (int32 HashIndex = 0, LocalHashSize = HashSize; HashIndex < LocalHashSize; ++HashIndex)
1056 {
1057 Ar.Logf(TEXT(" Hash[%i]"),HashIndex);
1058
1059 // iterate over all elements for the all hash entries
1060 // and dump info for all elements
1061 FSetElementId ElementId = GetTypedHash(HashIndex);
1062 while( ElementId.IsValidId() )
1063 {
1064 if( !IsValidId(ElementId) )
1065 {
1066 Ar.Logf(TEXT(" !!INVALID!! ElementId = %d"),ElementId.AsInteger());
1067 }
1068 else
1069 {
1070 Ar.Logf(TEXT(" VALID ElementId = %d"),ElementId.AsInteger());
1071 }
1072 ElementId = Elements[ElementId].HashNextId;
1073 }
1074 }
1075 }
1076
1079 {
1080 const bool bOtherSmaller = (Num() > OtherSet.Num());
1081 const UE_TSPARSE_SET& A = (bOtherSmaller ? OtherSet : *this);
1082 const UE_TSPARSE_SET& B = (bOtherSmaller ? *this : OtherSet);
1083
1084 UE_TSPARSE_SET Result;
1085 Result.Reserve(A.Num()); // Worst case is everything in smaller is in larger
1086
1087 for(TConstIterator SetIt(A);SetIt;++SetIt)
1088 {
1089 if(B.Contains(KeyFuncs::GetSetKey(*SetIt)))
1090 {
1091 Result.Add(*SetIt);
1092 }
1093 }
1094 return Result;
1095 }
1096
1099 {
1100 UE_TSPARSE_SET Result;
1101 Result.Reserve(Num() + OtherSet.Num()); // Worst case is 2 totally unique Sets
1102
1103 for(TConstIterator SetIt(*this);SetIt;++SetIt)
1104 {
1105 Result.Add(*SetIt);
1106 }
1107 for(TConstIterator SetIt(OtherSet);SetIt;++SetIt)
1108 {
1109 Result.Add(*SetIt);
1110 }
1111 return Result;
1112 }
1113
1116 {
1117 UE_TSPARSE_SET Result;
1118 Result.Reserve(Num()); // Worst case is no elements of this are in Other
1119
1120 for(TConstIterator SetIt(*this);SetIt;++SetIt)
1121 {
1122 if(!OtherSet.Contains(KeyFuncs::GetSetKey(*SetIt)))
1123 {
1124 Result.Add(*SetIt);
1125 }
1126 }
1127 return Result;
1128 }
1129
1138 {
1139 bool bIncludesSet = true;
1140 if (OtherSet.Num() <= Num())
1141 {
1143 {
1144 if (!Contains(KeyFuncs::GetSetKey(*OtherSetIt)))
1145 {
1146 bIncludesSet = false;
1147 break;
1148 }
1149 }
1150 }
1151 else
1152 {
1153 // Not possible to include if it is bigger than us
1154 bIncludesSet = false;
1155 }
1156 return bIncludesSet;
1157 }
1158
1161 {
1162 TArray<ElementType> Result;
1163 Result.Reserve(Num());
1164 for(TConstIterator SetIt(*this);SetIt;++SetIt)
1165 {
1166 Result.Add(*SetIt);
1167 }
1168 return Result;
1169 }
1170
1178 {
1179 Elements.CheckAddress(Addr);
1180 }
1181
1188 template <
1189 typename OtherKeyFuncs,
1190 typename AliasElementType = ElementType
1192 >
1200
1208 template <
1209 typename OtherKeyFuncs,
1210 typename OtherAllocator,
1211 typename AliasElementType = ElementType
1213 >
1221
1227 template <
1228 typename OtherKeyFuncs,
1229 typename OtherAllocator,
1230 typename AliasElementType = ElementType
1232 >
1242
1248 template <
1249 typename OtherKeyFuncs,
1250 typename AliasElementType = ElementType
1252 >
1263
1264private:
1266 template <typename PREDICATE_CLASS>
1267 class FElementCompareClass
1268 {
1270
1271 public:
1272 [[nodiscard]] UE_FORCEINLINE_HINT FElementCompareClass( const PREDICATE_CLASS& InPredicate )
1273 : Predicate( InPredicate )
1274 {
1275 }
1276
1277 [[nodiscard]] UE_FORCEINLINE_HINT bool operator()( const SetElementType& A,const SetElementType& B ) const
1278 {
1279 return Predicate( A.Value, B.Value );
1280 }
1281 };
1282
1284 using HashType = typename Allocator::HashAllocator::template ForElementType<FSetElementId>;
1285
1286 ElementArrayType Elements;
1287
1288 HashType Hash;
1289 int32 HashSize = 0;
1290
1291public:
1293 {
1294 checkf(!Writer.Is32BitTarget(), TEXT("UE_TSPARSE_SET does not currently support freezing for 32bits"));
1296 {
1297 this->Elements.WriteMemoryImage(Writer);
1298 this->Hash.WriteMemoryImage(Writer, StaticGetTypeLayoutDesc<FSetElementId>(), this->HashSize);
1299 Writer.WriteBytes(this->HashSize);
1300 }
1301 else
1302 {
1303 Writer.WriteBytes(UE_TSPARSE_SET());
1304 }
1305 }
1306
1307 void CopyUnfrozen(const FMemoryUnfreezeContent& Context, void* Dst) const
1308 {
1310 {
1311 UE_TSPARSE_SET* DstObject = static_cast<UE_TSPARSE_SET*>(Dst);
1312 this->Elements.CopyUnfrozen(Context, &DstObject->Elements);
1313
1314 ::new((void*)&DstObject->Hash) HashType();
1315 DstObject->Hash.ResizeAllocation(0, this->HashSize, sizeof(FSetElementId));
1316 FMemory::Memcpy(DstObject->Hash.GetAllocation(), this->Hash.GetAllocation(), sizeof(FSetElementId) * this->HashSize);
1317 DstObject->HashSize = this->HashSize;
1318 }
1319 else
1320 {
1321 ::new(Dst) UE_TSPARSE_SET();
1322 }
1323 }
1324
1325 static void AppendHash(const FPlatformTypeLayoutParameters& LayoutParams, FSHA1& Hasher)
1326 {
1327 ElementArrayType::AppendHash(LayoutParams, Hasher);
1328 }
1329
1330private:
1331
1332 [[nodiscard]] UE_FORCEINLINE_HINT FSetElementId& GetTypedHash(int32 HashIndex) const
1333 {
1334 return ((FSetElementId*)Hash.GetAllocation())[HashIndex & (HashSize - 1)];
1335 }
1336
1338 inline void LinkElement(SizeType ElementIndex, const SetElementType& Element, uint32 KeyHash) const
1339 {
1340 // Compute the hash bucket the element goes in.
1341 Element.HashIndex = KeyHash & (HashSize - 1);
1342
1343 // Link the element into the hash bucket.
1344 FSetElementId& TypedHash = GetTypedHash(Element.HashIndex);
1345 Element.HashNextId = TypedHash;
1346 TypedHash = FSetElementId::FromInteger(ElementIndex);
1347 }
1348
1350 UE_FORCEINLINE_HINT void HashElement(SizeType ElementIndex, const SetElementType& Element) const
1351 {
1352 LinkElement(ElementIndex, Element, KeyFuncs::GetKeyHash(KeyFuncs::GetSetKey(Element.Value)));
1353 }
1354
1356 void UnhashElements()
1357 {
1358 FSetElementId* HashPtr = Hash.GetAllocation();
1359
1360 // Check if it should be faster to clear the hash by going through elements instead of resetting the whole hash
1361 if (Num() < (HashSize / 4))
1362 {
1363 // Faster path: only reset hash buckets to invalid for elements in the hash
1364 for (const SetElementType& Element: Elements)
1365 {
1366 HashPtr[Element.HashIndex] = FSetElementId();
1367 }
1368 }
1369 else
1370 {
1371 static_assert(FSetElementId().AsInteger() == -1);
1372 FMemory::Memset(HashPtr, 0xFF, HashSize * sizeof(FSetElementId));
1373 }
1374 }
1375
1384 {
1385 // If the hash hasn't been created yet, or is smaller than the desired hash size, rehash.
1386 // If shrinking is allowed and the hash is bigger than the desired hash size, rehash.
1387 return ((NumHashedElements > 0 && HashSize < DesiredHashSize) || (AllowShrinking == EAllowShrinking::Yes && HashSize > DesiredHashSize));
1388 }
1389
1396 bool ConditionalRehash(int32 NumHashedElements, EAllowShrinking AllowShrinking)
1397 {
1398 // Calculate the desired hash size for the specified number of elements.
1399 const int32 DesiredHashSize = Allocator::GetNumberOfHashBuckets(NumHashedElements);
1400
1402 {
1403 HashSize = DesiredHashSize;
1404 Rehash();
1405 return true;
1406 }
1407
1408 return false;
1409 }
1410
1412 void Rehash()
1413 {
1415
1416 if (HashSize)
1417 {
1418 // Add the existing elements to the new hash.
1419 for(typename ElementArrayType::TConstIterator ElementIt(Elements);ElementIt;++ElementIt)
1420 {
1421 HashElement(ElementIt.GetIndex(), *ElementIt);
1422 }
1423 }
1424 }
1425
1427 template<bool bConst, bool bRangedFor = false>
1428 class TBaseIterator
1429 {
1430 private:
1431 friend class UE_TSPARSE_SET;
1432
1433 typedef std::conditional_t<bConst,const ElementType,ElementType> ItElementType;
1434
1435 public:
1436 typedef std::conditional_t<
1437 bConst,
1438 std::conditional_t<bRangedFor, typename ElementArrayType::TRangedForConstIterator, typename ElementArrayType::TConstIterator>,
1439 std::conditional_t<bRangedFor, typename ElementArrayType::TRangedForIterator, typename ElementArrayType::TIterator >
1440 > ElementItType;
1441
1442 [[nodiscard]] UE_FORCEINLINE_HINT TBaseIterator(const ElementItType& InElementIt)
1443 : ElementIt(InElementIt)
1444 {
1445 }
1446
1448 UE_FORCEINLINE_HINT TBaseIterator& operator++()
1449 {
1450 ++ElementIt;
1451 return *this;
1452 }
1453
1455 [[nodiscard]] UE_FORCEINLINE_HINT explicit operator bool() const
1456 {
1457 return !!ElementIt;
1458 }
1460 [[nodiscard]] UE_FORCEINLINE_HINT bool operator!() const
1461 {
1462 return !(bool)*this;
1463 }
1464
1465 // Accessors.
1467 {
1468 return FSetElementId::FromInteger(ElementIt.GetIndex());
1469 }
1470 [[nodiscard]] UE_FORCEINLINE_HINT ItElementType* operator->() const
1471 {
1472 return &ElementIt->Value;
1473 }
1474 [[nodiscard]] UE_FORCEINLINE_HINT ItElementType& operator*() const
1475 {
1476 return ElementIt->Value;
1477 }
1478
1479 [[nodiscard]] UE_FORCEINLINE_HINT bool operator!=(const TBaseIterator& Rhs) const { return ElementIt != Rhs.ElementIt; }
1480 [[nodiscard]] UE_FORCEINLINE_HINT bool operator==(const TBaseIterator& Rhs) const { return ElementIt == Rhs.ElementIt; }
1481
1482 ElementItType ElementIt;
1483 };
1484
1486 template<bool bConst>
1487 class TBaseKeyIterator
1488 {
1489 private:
1490 typedef std::conditional_t<bConst, const UE_TSPARSE_SET, UE_TSPARSE_SET> SetType;
1491 typedef std::conditional_t<bConst,const ElementType,ElementType> ItElementType;
1492 typedef typename TTypeTraits<typename KeyFuncs::KeyType>::ConstPointerType ReferenceOrValueType;
1493
1494 public:
1495 using KeyArgumentType =
1496 std::conditional_t<
1497 std::is_reference_v<ReferenceOrValueType>,
1499 KeyInitType
1500 >;
1501
1503 [[nodiscard]] inline TBaseKeyIterator(SetType& InSet, KeyArgumentType InKey)
1504 : Set (InSet)
1505 , Key (InKey) //-V1041
1506 , Index(INDEX_NONE)
1507 {
1508 if (Set.HashSize)
1509 {
1510 NextIndex = Set.GetTypedHash(KeyFuncs::GetKeyHash(Key)).AsInteger();
1511 ++(*this);
1512 }
1513 else
1514 {
1515 NextIndex = INDEX_NONE;
1516 }
1517 }
1518
1520 inline TBaseKeyIterator& operator++()
1521 {
1522 Index = NextIndex;
1523
1524 while (Index != INDEX_NONE)
1525 {
1526 NextIndex = Set.Elements[Index].HashNextId.AsInteger();
1527 checkSlow(Index != NextIndex);
1528
1529 if (KeyFuncs::Matches(KeyFuncs::GetSetKey(Set.Elements[Index].Value),Key))
1530 {
1531 break;
1532 }
1533
1534 Index = NextIndex;
1535 }
1536 return *this;
1537 }
1538
1540 [[nodiscard]] UE_FORCEINLINE_HINT explicit operator bool() const
1541 {
1542 return Index != INDEX_NONE;
1543 }
1545 [[nodiscard]] UE_FORCEINLINE_HINT bool operator!() const
1546 {
1547 return !(bool)*this;
1548 }
1549
1550 // Accessors.
1552 {
1554 }
1555 [[nodiscard]] UE_FORCEINLINE_HINT ItElementType* operator->() const
1556 {
1557 return &Set.Elements[Index].Value;
1558 }
1559 [[nodiscard]] UE_FORCEINLINE_HINT ItElementType& operator*() const
1560 {
1561 return Set.Elements[Index].Value;
1562 }
1563
1564 protected:
1565 SetType& Set;
1566 ReferenceOrValueType Key;
1567 SizeType Index;
1568 SizeType NextIndex;
1569 };
1570
1571public:
1572
1574 class TConstIterator : public TBaseIterator<true>
1575 {
1576 friend class UE_TSPARSE_SET;
1577
1578 public:
1580 : TBaseIterator<true>(InSet.Elements.begin())
1581 {
1582 }
1583 };
1584
1586 class TIterator : public TBaseIterator<false>
1587 {
1588 friend class UE_TSPARSE_SET;
1589
1590 public:
1592 : TBaseIterator<false>(InSet.Elements.begin())
1593 , Set (InSet)
1594 {
1595 }
1596
1599 {
1600 Set.RemoveByIndex(TBaseIterator<false>::ElementIt.GetIndex());
1601 }
1602
1603 private:
1605 };
1606
1609
1611 class TConstKeyIterator : public TBaseKeyIterator<true>
1612 {
1613 private:
1614 using Super = TBaseKeyIterator<true>;
1615
1616 public:
1617 using KeyArgumentType = typename Super::KeyArgumentType;
1618
1623 };
1624
1626 class TKeyIterator : public TBaseKeyIterator<false>
1627 {
1628 private:
1629 using Super = TBaseKeyIterator<false>;
1630
1631 public:
1632 using KeyArgumentType = typename Super::KeyArgumentType;
1633
1638
1640 inline void RemoveCurrent()
1641 {
1642 this->Set.RemoveByIndex(TBaseKeyIterator<false>::Index);
1644 }
1645 };
1646
1649 {
1650 return TIterator(*this);
1651 }
1652
1658
1659 friend struct TSETPRIVATEFRIEND;
1660
1661public:
1667 {
1668 return TRangedForIterator(Elements.begin());
1669 }
1671 {
1672 return TRangedForConstIterator(Elements.begin());
1673 }
1675 {
1676 return TRangedForIterator(Elements.end());
1677 }
1679 {
1680 return TRangedForConstIterator(Elements.end());
1681 }
1682
1683 // Maps are deliberately prevented from being hashed or compared, because this would hide potentially major performance problems behind default operations.
1684 friend uint32 GetTypeHash(const UE_TSPARSE_SET& Set) = delete;
1685 friend bool operator==(const UE_TSPARSE_SET&, const UE_TSPARSE_SET&) = delete;
1686 friend bool operator!=(const UE_TSPARSE_SET&, const UE_TSPARSE_SET&) = delete;
1687};
1688
1689template <typename RangeType>
1691
1692namespace Freeze
1693{
1694 template<typename ElementType, typename KeyFuncs, typename Allocator>
1696 {
1697 Object.WriteMemoryImage(Writer);
1698 }
1699
1700 template<typename ElementType, typename KeyFuncs, typename Allocator>
1706
1707 template<typename ElementType, typename KeyFuncs, typename Allocator>
1709 {
1711 return DefaultAppendHash(TypeDesc, LayoutParams, Hasher);
1712 }
1713}
1714
1716
1717struct TSETPRIVATEFRIEND
1718{
1720 template<typename ElementType, typename KeyFuncs,typename Allocator>
1722 {
1723 // Load the set's new elements.
1724 Ar << Set.Elements;
1725
1726 if(Ar.IsLoading() || (Ar.IsModifyingWeakAndStrongReferences() && !Ar.IsSaving()))
1727 {
1728 // Free the old hash.
1729 Set.Hash.ResizeAllocation(0,0,sizeof(FSetElementId));
1730 Set.HashSize = 0;
1731
1732 // Hash the newly loaded elements.
1733 Set.ConditionalRehash(Set.Elements.Num(), EAllowShrinking::No);
1734 }
1735
1736 return Ar;
1737 }
1738
1740 template<typename ElementType, typename KeyFuncs,typename Allocator>
1742 {
1743 Slot << Set.Elements;
1744
1746 {
1747 // Free the old hash.
1748 Set.Hash.ResizeAllocation(0, 0, sizeof(FSetElementId));
1749 Set.HashSize = 0;
1750
1751 // Hash the newly loaded elements.
1752 Set.ConditionalRehash(Set.Elements.Num(), EAllowShrinking::No);
1753 }
1754 }
1755
1756 // Legacy comparison operators. Note that these also test whether the set's elements were added in the same order!
1757 template<typename ElementType, typename KeyFuncs,typename Allocator>
1759 {
1760 return A.Elements == B.Elements;
1761 }
1762};
1763
1765template<typename ElementType, typename KeyFuncs,typename Allocator>
1767{
1768 return TSETPRIVATEFRIEND::Serialize(Ar, Set);
1769}
1770
1772template<typename ElementType, typename KeyFuncs,typename Allocator>
1774{
1775 TSETPRIVATEFRIEND::SerializeStructured(Ar, Set);
1776}
1777
1778// Legacy comparison operators. Note that these also test whether the set's elements were added in the same order!
1779template<typename ElementType, typename KeyFuncs,typename Allocator>
1781{
1782 return TSETPRIVATEFRIEND::LegacyCompareEqual(A, B);
1783}
1784template<typename ElementType, typename KeyFuncs,typename Allocator>
1786{
1787 return !TSETPRIVATEFRIEND::LegacyCompareEqual(A, B);
1788}
1789
1790template <typename ElementType, typename KeyFuncs, typename Allocator> struct TIsTSet< UE_TSPARSE_SET<ElementType, KeyFuncs, Allocator>> { enum { Value = true }; };
1791template <typename ElementType, typename KeyFuncs, typename Allocator> struct TIsTSet<const UE_TSPARSE_SET<ElementType, KeyFuncs, Allocator>> { enum { Value = true }; };
1792template <typename ElementType, typename KeyFuncs, typename Allocator> struct TIsTSet< volatile UE_TSPARSE_SET<ElementType, KeyFuncs, Allocator>> { enum { Value = true }; };
1793template <typename ElementType, typename KeyFuncs, typename Allocator> struct TIsTSet<const volatile UE_TSPARSE_SET<ElementType, KeyFuncs, Allocator>> { enum { Value = true }; };
1794
1795#undef TSETPRIVATEFRIEND
constexpr bool operator!(EUpdateTransformFlags Value)
Definition ActorComponent.h:116
EAllowShrinking
Definition AllowShrinking.h:10
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define checkf(expr, format,...)
Definition AssertionMacros.h:315
UE_FORCEINLINE_HINT FLinearColor operator*(float Scalar, const FLinearColor &Color)
Definition Color.h:473
@ INDEX_NONE
Definition CoreMiscDefines.h:150
#define UE_STATIC_ASSERT_WARN(bExpression, Message)
Definition CoreMiscDefines.h:431
EInPlace
Definition CoreMiscDefines.h:162
EConstEval
Definition CoreMiscDefines.h:161
@ ConstEval
Definition CoreMiscDefines.h:161
#define UE_TSPARSE_SET
Definition SparseSet.h.inl:1431
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::SIZE_T SIZE_T
An unsigned integer the same size as a pointer, the same as UPTRINT.
Definition Platform.h:1150
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define UE_FORCEINLINE_HINT
Definition Platform.h:723
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
return true
Definition ExternalRpcRegistry.cpp:601
#define PRAGMA_ENABLE_DEPRECATION_WARNINGS
Definition GenericPlatformCompilerPreSetup.h:12
#define PRAGMA_DISABLE_DEPRECATION_WARNINGS
Definition GenericPlatformCompilerPreSetup.h:8
UE_FORCEINLINE_HINT bool operator!=(const FIndexedPointer &Other) const
Definition LockFreeList.h:76
#define DECLARE_TEMPLATE_INTRINSIC_TYPE_LAYOUT(TemplatePrefix, T)
Definition MemoryLayout.h:661
@ Num
Definition MetalRHIPrivate.h:234
const bool
Definition NetworkReplayStreaming.h:178
TIndexedContainerIterator< const TArray< FPreviewAttachedObjectPair >, const FPreviewAttachedObjectPair, int32 > TConstIterator
Definition PreviewAssetAttachComponent.h:69
TIndexedContainerIterator< TArray< FPreviewAttachedObjectPair >, FPreviewAttachedObjectPair, int32 > TIterator
Definition PreviewAssetAttachComponent.h:68
#define UE_REQUIRES(...)
Definition Requires.h:86
void MoveByRelocate(T &A, T &B)
Definition SetUtilities.h:82
bool LegacyCompareNotEqual(const UE_TSPARSE_SET< ElementType, KeyFuncs, Allocator > &A, const UE_TSPARSE_SET< ElementType, KeyFuncs, Allocator > &B)
Definition SparseSet.h.inl:1785
bool LegacyCompareEqual(const UE_TSPARSE_SET< ElementType, KeyFuncs, Allocator > &A, const UE_TSPARSE_SET< ElementType, KeyFuncs, Allocator > &B)
Definition SparseSet.h.inl:1780
FArchive & operator<<(FArchive &Ar, UE_TSPARSE_SET< ElementType, KeyFuncs, Allocator > &Set)
Definition SparseSet.h.inl:1766
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTempIfPossible(T &&Obj) noexcept
Definition UnrealTemplate.h:538
void Move(T &A, typename TMoveSupportTraits< T >::Copy B)
Definition UnrealTemplate.h:24
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition Archive.h:1208
UE_FORCEINLINE_HINT bool IsModifyingWeakAndStrongReferences() const
Definition Archive.h:462
UE_FORCEINLINE_HINT bool IsLoading() const
Definition Archive.h:236
UE_FORCEINLINE_HINT bool IsSaving() const
Definition Archive.h:248
virtual void CountBytes(SIZE_T InNum, SIZE_T InMax)
Definition Archive.h:125
Definition MemoryImageWriter.h:14
CORE_API uint32 WriteBytes(const void *Data, uint32 Size)
Definition MemoryImage.cpp:2143
bool Is32BitTarget() const
Definition MemoryImageWriter.h:26
Definition MemoryImageWriter.h:78
Definition OutputDevice.h:133
void Logf(const FmtType &Fmt)
Definition OutputDevice.h:234
Definition SecureHash.h:314
Definition SetUtilities.h:95
static UE_FORCEINLINE_HINT FSetElementId FromInteger(int32 Integer)
Definition SetUtilities.h:121
constexpr UE_FORCEINLINE_HINT int32 AsInteger() const
Definition SetUtilities.h:116
UE_FORCEINLINE_HINT bool IsValidId() const
Definition SetUtilities.h:101
Definition StructuredArchiveSlots.h:52
Definition ArrayView.h:139
Definition Array.h:670
Definition ScriptSparseSet.h:26
void SortFreeList()
Definition SparseArray.h:322
int32 Num() const
Definition SparseArray.h:470
bool Compact()
Definition SparseArray.h:412
int32 Max() const
Definition SparseArray.h:476
void RemoveAtUninitialized(int32 Index, int32 Count=1)
Definition SparseArray.h:191
FSparseArrayAllocationInfo AddUninitialized()
Definition SparseArray.h:117
bool IsValidIndex(int32 Index) const
Definition SparseArray.h:481
bool IsAllocated(int32 Index) const
Definition SparseArray.h:486
void Shrink()
Definition SparseArray.h:256
void Reserve(int32 ExpectedNumElements)
Definition SparseArray.h:219
int32 GetMaxIndex() const
Definition SparseArray.h:460
bool IsEmpty() const
Definition SparseArray.h:465
Definition SparseArray.h:524
void RemoveAt(int32 Index, int32 Count=1)
Definition SparseArray.h:650
SIZE_T GetAllocatedSize(void) const
Definition SparseArray.h:808
void StableSort(const PREDICATE_CLASS &Predicate)
Definition SparseArray.h:746
void CountBytes(FArchive &Ar) const
Definition SparseArray.h:814
void Reset()
Definition SparseArray.h:682
UE_FORCEINLINE_HINT void CheckAddress(const ElementType *Addr) const
Definition SparseArray.h:1036
void Sort(const PREDICATE_CLASS &Predicate)
Definition SparseArray.h:726
bool CompactStable()
Definition SparseArray.h:703
void Empty(int32 ExpectedNumElements=0)
Definition SparseArray.h:666
int32 FindArbitraryElementIndex() const
Definition SparseArray.h:791
Definition SparseSetElement.h:80
CORE_API FArchive & GetUnderlyingArchive() const
Definition StructuredArchiveSlots.cpp:7
CORE_API void Reserve(int32 CharacterCount)
Definition String.cpp.inl:307
Definition SparseSet.h.inl:1575
UE_FORCEINLINE_HINT TConstIterator(const UE_TSPARSE_SET &InSet)
Definition SparseSet.h.inl:1579
Definition SparseSet.h.inl:1612
typename Super::KeyArgumentType KeyArgumentType
Definition SparseSet.h.inl:1617
UE_FORCEINLINE_HINT TConstKeyIterator(const UE_TSPARSE_SET &InSet, KeyArgumentType InKey)
Definition SparseSet.h.inl:1619
Definition SparseSet.h.inl:1587
TIterator(UE_TSPARSE_SET &InSet)
Definition SparseSet.h.inl:1591
UE_FORCEINLINE_HINT void RemoveCurrent()
Definition SparseSet.h.inl:1598
Definition SparseSet.h.inl:1627
UE_FORCEINLINE_HINT TKeyIterator(UE_TSPARSE_SET &InSet, KeyArgumentType InKey)
Definition SparseSet.h.inl:1634
typename Super::KeyArgumentType KeyArgumentType
Definition SparseSet.h.inl:1632
void RemoveCurrent()
Definition SparseSet.h.inl:1640
Definition SparseSet.h.inl:53
UE_TSPARSE_SET & operator=(const UE_TSPARSE_SET &Copy)
Definition SparseSet.h.inl:126
UE_TSPARSE_SET Intersect(const UE_TSPARSE_SET &OtherSet) const
Definition SparseSet.h.inl:1078
friend bool operator==(const UE_TSPARSE_SET &, const UE_TSPARSE_SET &)=delete
void Append(const UE_TSPARSE_SET< ElementType, KeyFuncs, OtherAllocator > &OtherSet)
Definition SparseSet.h.inl:651
static constexpr bool bHasIntrusiveUnsetOptionalState
Definition SparseSet.h.inl:110
UE_FORCEINLINE_HINT TConstIterator CreateConstIterator() const
Definition SparseSet.h.inl:1654
void Append(UE_TSPARSE_SET< ElementType, KeyFuncs, OtherAllocator > &&OtherSet)
Definition SparseSet.h.inl:661
UE_TSPARSE_SET(FIntrusiveUnsetOptionalState Tag)
Definition SparseSet.h.inl:113
bool IsValidId(FSetElementId Id) const
Definition SparseSet.h.inl:369
UE_FORCEINLINE_HINT int32 Num() const
Definition SparseSet.h.inl:347
FSetElementId FindId(KeyInitType Key) const
Definition SparseSet.h.inl:784
typename Allocator::SparseArrayAllocator::ElementAllocator::SizeType SizeType
Definition SparseSet.h.inl:59
ElementType * FindByHash(uint32 KeyHash, const ComparableKey &Key)
Definition SparseSet.h.inl:839
UE_FORCEINLINE_HINT const ElementType * Find(KeyInitType Key) const
Definition SparseSet.h.inl:828
ElementType * Find(KeyInitType Key)
Definition SparseSet.h.inl:810
UE_FORCEINLINE_HINT FSetElementId Add(const InElementType &InElement, bool *bIsAlreadyInSetPtr=nullptr)
Definition SparseSet.h.inl:409
UE_FORCEINLINE_HINT TRangedForConstIterator begin() const
Definition SparseSet.h.inl:1670
int32 RemoveStable(KeyInitType Key)
Definition SparseSet.h.inl:912
UE_TSPARSE_SET Union(const UE_TSPARSE_SET &OtherSet) const
Definition SparseSet.h.inl:1098
UE_TSPARSE_SET & operator=(std::initializer_list< ElementType > InitList)
Definition SparseSet.h.inl:210
UE_FORCEINLINE_HINT SIZE_T GetAllocatedSize(void) const
Definition SparseSet.h.inl:323
FSetElementId Emplace(ArgType &&Arg, bool *bIsAlreadyInSetPtr=nullptr)
Definition SparseSet.h.inl:534
TBaseIterator< false, true > TRangedForIterator
Definition SparseSet.h.inl:1608
void RemoveStable(FSetElementId ElementId)
Definition SparseSet.h.inl:722
void SortFreeList()
Definition SparseSet.h.inl:1005
const ElementType * FindArbitraryElement() const
Definition SparseSet.h.inl:774
UE_FORCEINLINE_HINT ElementType & FindOrAdd(InElementType &&InElement, bool *bIsAlreadyInSetPtr=nullptr)
Definition SparseSet.h.inl:429
InElementType ElementType
Definition SparseSet.h.inl:55
static void AppendHash(const FPlatformTypeLayoutParameters &LayoutParams, FSHA1 &Hasher)
Definition SparseSet.h.inl:1325
UE_FORCEINLINE_HINT const ElementType & Get(FSetElementId Id) const
Definition SparseSet.h.inl:397
bool VerifyHashElementsKey(KeyInitType Key) const
Definition SparseSet.h.inl:1032
ElementType * FindArbitraryElement()
Definition SparseSet.h.inl:767
bool Includes(const UE_TSPARSE_SET< ElementType, KeyFuncs, Allocator > &OtherSet) const
Definition SparseSet.h.inl:1137
FSetElementId EmplaceByHash(uint32 KeyHash, ArgType &&Args, bool *bIsAlreadyInSetPtr=nullptr)
Definition SparseSet.h.inl:586
UE_FORCEINLINE_HINT ElementType & Get(FSetElementId Id)
Definition SparseSet.h.inl:391
void Append(TArrayView< const ElementType > InElements)
Definition SparseSet.h.inl:626
void WriteMemoryImage(FMemoryImageWriter &Writer) const
Definition SparseSet.h.inl:1292
UE_FORCEINLINE_HINT TRangedForConstIterator end() const
Definition SparseSet.h.inl:1678
void Append(TArray< ElementType, ArrayAllocator > &&InElements)
Definition SparseSet.h.inl:636
bool operator==(FIntrusiveUnsetOptionalState Tag) const
Definition SparseSet.h.inl:117
UE_FORCEINLINE_HINT FSetElementId AddByHash(uint32 KeyHash, const InElementType &InElement, bool *bIsAlreadyInSetPtr=nullptr)
Definition SparseSet.h.inl:443
bool ContainsByHash(uint32 KeyHash, const ComparableKey &Key) const
Definition SparseSet.h.inl:964
int32 RemoveByHash(uint32 KeyHash, const ComparableKey &Key)
Definition SparseSet.h.inl:933
void StableSort(const PREDICATE_CLASS &Predicate)
Definition SparseSet.h.inl:991
void Sort(const PREDICATE_CLASS &Predicate)
Definition SparseSet.h.inl:978
UE_TSPARSE_SET(UE_TSPARSE_SET< ElementType, KeyFuncs, OtherAllocator > &&Other)
Definition SparseSet.h.inl:177
FSetElementId FindIdByHash(uint32 KeyHash, const ComparableKey &Key) const
Definition SparseSet.h.inl:795
void Dump(FOutputDevice &Ar)
Definition SparseSet.h.inl:1014
UE_FORCEINLINE_HINT const ElementType & operator[](FSetElementId Id) const
Definition SparseSet.h.inl:385
void CopyUnfrozen(const FMemoryUnfreezeContent &Context, void *Dst) const
Definition SparseSet.h.inl:1307
void Append(const UE_TSPARSE_SET< typename TContainerElementTypeCompatibility< ElementType >::CopyFromOtherType, OtherKeyFuncs, OtherAllocator > &OtherSet)
Definition SparseSet.h.inl:1233
UE_FORCEINLINE_HINT ElementType & FindOrAdd(const InElementType &InElement, bool *bIsAlreadyInSetPtr=nullptr)
Definition SparseSet.h.inl:425
void CountBytes(FArchive &Ar) const
Definition SparseSet.h.inl:329
void DumpHashElements(FOutputDevice &Ar)
Definition SparseSet.h.inl:1053
TArray< ElementType > Array() const
Definition SparseSet.h.inl:1160
KeyFuncs KeyFuncsType
Definition SparseSet.h.inl:56
UE_FORCEINLINE_HINT ~UE_TSPARSE_SET()
Definition SparseSet.h.inl:101
UE_TSPARSE_SET & operator=(UE_TSPARSE_SET< typename TContainerElementTypeCompatibility< ElementType >::CopyFromOtherType, OtherKeyFuncs, Allocator > &&Other)
Definition SparseSet.h.inl:1193
UE_TSPARSE_SET & operator=(UE_TSPARSE_SET &&Other)
Definition SparseSet.h.inl:165
void Reset()
Definition SparseSet.h.inl:244
UE_FORCEINLINE_HINT void Relax()
Definition SparseSet.h.inl:313
UE_FORCEINLINE_HINT TRangedForIterator begin()
Definition SparseSet.h.inl:1666
friend uint32 GetTypeHash(const UE_TSPARSE_SET &Set)=delete
void Empty(int32 ExpectedNumElements=0)
Definition SparseSet.h.inl:221
TPair< FSetElementId, bool > EmplaceByHash(EInPlace, uint32 KeyHash, ArgTypes &&... InArgs)
Definition SparseSet.h.inl:611
UE_FORCEINLINE_HINT int32 GetMaxIndex() const
Definition SparseSet.h.inl:359
int32 Remove(KeyInitType Key)
Definition SparseSet.h.inl:898
void Remove(FSetElementId ElementId)
Definition SparseSet.h.inl:713
UE_FORCEINLINE_HINT UE_TSPARSE_SET(const UE_TSPARSE_SET &Copy)
Definition SparseSet.h.inl:85
UE_FORCEINLINE_HINT FSetElementId AddByHash(uint32 KeyHash, InElementType &&InElement, bool *bIsAlreadyInSetPtr=nullptr)
Definition SparseSet.h.inl:447
UE_FORCEINLINE_HINT UE_TSPARSE_SET(TArray< ElementType > &&InArray)
Definition SparseSet.h.inl:95
friend bool operator!=(const UE_TSPARSE_SET &, const UE_TSPARSE_SET &)=delete
void Reserve(int32 Number)
Definition SparseSet.h.inl:284
const ElementType * FindByHash(uint32 KeyHash, const ComparableKey &Key) const
Definition SparseSet.h.inl:853
Allocator AllocatorType
Definition SparseSet.h.inl:57
UE_FORCEINLINE_HINT int32 Max() const
Definition SparseSet.h.inl:353
UE_FORCEINLINE_HINT void CheckAddress(const ElementType *Addr) const
Definition SparseSet.h.inl:1177
TPair< FSetElementId, bool > Emplace(EInPlace, ArgTypes &&... InArgs)
Definition SparseSet.h.inl:558
UE_TSPARSE_SET(const UE_TSPARSE_SET< ElementType, KeyFuncs, OtherAllocator > &Other)
Definition SparseSet.h.inl:185
UE_FORCEINLINE_HINT TRangedForIterator end()
Definition SparseSet.h.inl:1674
TBaseIterator< true, true > TRangedForConstIterator
Definition SparseSet.h.inl:1607
UE_FORCEINLINE_HINT TIterator CreateIterator()
Definition SparseSet.h.inl:1648
UE_FORCEINLINE_HINT constexpr UE_TSPARSE_SET()=default
UE_TSPARSE_SET & operator=(const UE_TSPARSE_SET< ElementType, KeyFuncs, OtherAllocator > &Other)
Definition SparseSet.h.inl:202
ElementType & FindOrAddByHash(uint32 KeyHash, ElementReferenceType &&InElement, bool *bIsAlreadyInSetPtr=nullptr)
Definition SparseSet.h.inl:462
UE_FORCEINLINE_HINT bool Contains(KeyInitType Key) const
Definition SparseSet.h.inl:953
consteval UE_TSPARSE_SET(EConstEval)
Definition SparseSet.h.inl:78
UE_TSPARSE_SET & operator=(UE_TSPARSE_SET< ElementType, KeyFuncs, OtherAllocator > &&Other)
Definition SparseSet.h.inl:193
UE_TSPARSE_SET Difference(const UE_TSPARSE_SET &OtherSet) const
Definition SparseSet.h.inl:1115
void Append(UE_TSPARSE_SET< typename TContainerElementTypeCompatibility< ElementType >::CopyFromOtherType, OtherKeyFuncs, Allocator > &&OtherSet)
Definition SparseSet.h.inl:1253
UE_TSPARSE_SET(UE_TSPARSE_SET &&Other)
Definition SparseSet.h.inl:158
void Compact()
Definition SparseSet.h.inl:264
UE_TSPARSE_SET & operator=(const UE_TSPARSE_SET< typename TContainerElementTypeCompatibility< ElementType >::CopyFromOtherType, OtherKeyFuncs, OtherAllocator > &Other)
Definition SparseSet.h.inl:1214
void Shrink()
Definition SparseSet.h.inl:257
UE_TSPARSE_SET(std::initializer_list< ElementType > InitList)
Definition SparseSet.h.inl:151
void Append(std::initializer_list< ElementType > InitList)
Definition SparseSet.h.inl:671
UE_FORCEINLINE_HINT ElementType & operator[](FSetElementId Id)
Definition SparseSet.h.inl:379
void CompactStable()
Definition SparseSet.h.inl:274
UE_FORCEINLINE_HINT FSetElementId Add(InElementType &&InElement, bool *bIsAlreadyInSetPtr=nullptr)
Definition SparseSet.h.inl:413
bool IsEmpty() const
Definition SparseSet.h.inl:341
UE_FORCEINLINE_HINT UE_TSPARSE_SET(TArrayView< const ElementType > InArrayView)
Definition SparseSet.h.inl:90
Definition Array.h:3955
UE_NODEBUG void IntrinsicWriteMemoryImage(FMemoryImageWriter &Writer, const TArray< T, AllocatorType > &Object, const FTypeLayoutDesc &)
Definition Array.h:3957
CORE_API uint32 DefaultAppendHash(const FTypeLayoutDesc &TypeDesc, const FPlatformTypeLayoutParameters &LayoutParams, FSHA1 &Hasher)
Definition MemoryImage.cpp:575
UE_NODEBUG uint32 IntrinsicUnfrozenCopy(const FMemoryUnfreezeContent &Context, const TArray< T, AllocatorType > &Object, void *OutDst)
Definition Array.h:3963
UE_NODEBUG uint32 IntrinsicAppendHash(const TArray< T, AllocatorType > *DummyObject, const FTypeLayoutDesc &TypeDesc, const FPlatformTypeLayoutParameters &LayoutParams, FSHA1 &Hasher)
Definition Array.h:3970
FNameFuncs< typename TGetKeyType< MapType >::Type > KeyFuncs
Definition PerPlatformProperties.h:107
bool operator==(const FCachedAssetKey &A, const FCachedAssetKey &B)
Definition AssetDataMap.h:501
@ Element
Definition Visu.h:18
void Rehash(HashType &Hash, int32 HashSize)
Definition SparseSetElement.h:132
void CopyHash(HashType &Hash, int32 &HashSize, const HashType &Copy, int32 HashSizeCopy)
Definition SparseSetElement.h:117
CORE_API void OnInvalidSetNum(unsigned long long NewNum)
Definition ContainerHelpers.cpp:12
FORCEINLINE UE_STRING_CLASS RhsType && Rhs
Definition String.cpp.inl:718
@ false
Definition radaudio_common.h:23
U16 Index
Definition radfft.cpp:71
Definition IntrusiveUnsetOptionalState.h:71
static UE_FORCEINLINE_HINT void * Memcpy(void *Dest, const void *Src, SIZE_T Count)
Definition UnrealMemory.h:160
static UE_FORCEINLINE_HINT void * Memset(void *Dest, uint8 Char, SIZE_T Count)
Definition UnrealMemory.h:119
Definition MemoryLayout.h:799
Definition SparseArray.h:31
Definition MemoryLayout.h:108
Definition ContainerAllocationPolicies.h:256
InElementType CopyFromOtherType
Definition ContainerElementTypeCompatibility.h:17
static constexpr void CopyingFromOtherType()
Definition ContainerElementTypeCompatibility.h:29
Definition MemoryLayout.h:626
Definition SetUtilities.h:14
@ Value
Definition SetUtilities.h:14
Definition RetainedRef.h:62
Definition CompactSet.h.inl:1619
static FArchive & Serialize(FArchive &Ar, UE_TSPARSE_SET< ElementType, KeyFuncs, Allocator > &Set)
Definition SparseSet.h.inl:1721
static void SerializeStructured(FStructuredArchive::FSlot Slot, UE_TSPARSE_SET< ElementType, KeyFuncs, Allocator > &Set)
Definition SparseSet.h.inl:1741
static bool LegacyCompareEqual(const UE_TSPARSE_SET< ElementType, KeyFuncs, Allocator > &A, const UE_TSPARSE_SET< ElementType, KeyFuncs, Allocator > &B)
Definition SparseSet.h.inl:1758
Definition Tuple.h:652
TCallTraits< T >::ConstPointerType ConstPointerType
Definition UnrealTypeTraits.h:337