#pragma once #include "Set.h" #include "UnrealTemplate.h" #include "ChooseClass.h" // template // using TPair = TTuple; template class TPair { public: KeyType Key; ValueType Value; }; template class TPairInitializer { public: typename TRValueToLValueReference::Type Key; typename TRValueToLValueReference::Type Value; /** Initialization constructor. */ FORCEINLINE TPairInitializer(KeyInitType InKey, ValueInitType InValue) : Key(InKey) , Value(InValue) { } /** Implicit conversion to pair initializer. */ template FORCEINLINE TPairInitializer(const TPair& Pair) : Key(Pair.Key) , Value(Pair.Value) { } template operator TPair() const { #define StaticCast static_cast // Milxnor: ?? return TPair(StaticCast(Key), StaticCast(Value)); } }; template struct TDefaultMapKeyFuncs : BaseKeyFuncs, KeyType, bInAllowDuplicateKeys> { typedef typename TTypeTraits::ConstPointerType KeyInitType; typedef const TPairInitializer::ConstInitType, typename TTypeTraits::ConstInitType>& ElementInitType; static FORCEINLINE KeyInitType GetSetKey(ElementInitType Element) { return Element.Key; } static FORCEINLINE bool Matches(KeyInitType A, KeyInitType B) { return A == B; } static FORCEINLINE uint32 GetKeyHash(KeyInitType Key) { return GetTypeHash(Key); } }; template struct TDefaultMapHashableKeyFuncs : TDefaultMapKeyFuncs { // static_assert(THasGetTypeHash::Value, "TMap must have a hashable KeyType unless a custom key func is provided."); // T(R) }; template class TMapBase { template friend class TMapBase; friend struct TContainerTraits; public: typedef typename TTypeTraits::ConstPointerType KeyConstPointerType; typedef typename TTypeTraits::ConstInitType KeyInitType; typedef typename TTypeTraits::ConstInitType ValueInitType; typedef TPair ElementType; protected: TMapBase() = default; TMapBase(TMapBase&&) = default; TMapBase(const TMapBase&) = default; TMapBase& operator=(TMapBase&&) = default; TMapBase& operator=(const TMapBase&) = default; typedef TSet ElementSetType; /** The base of TMapBase iterators. */ template class TBaseIterator { public: typedef typename TChooseClass< bConst, typename TChooseClass::Result, typename TChooseClass::Result >::Result PairItType; private: typedef typename TChooseClass::Result MapType; typedef typename TChooseClass::Result ItKeyType; typedef typename TChooseClass::Result ItValueType; typedef typename TChooseClass::Result PairType; public: FORCEINLINE TBaseIterator(const PairItType& InElementIt) : PairIt(InElementIt) { } FORCEINLINE TBaseIterator& operator++() { ++PairIt; return *this; } /** conversion to "bool" returning true if the iterator is valid. */ FORCEINLINE explicit operator bool() const { return !!PairIt; } /** inverse of the "bool" operator */ FORCEINLINE bool operator !() const { return !(bool)*this; } FORCEINLINE friend bool operator==(const TBaseIterator& Lhs, const TBaseIterator& Rhs) { return Lhs.PairIt == Rhs.PairIt; } FORCEINLINE friend bool operator!=(const TBaseIterator& Lhs, const TBaseIterator& Rhs) { return Lhs.PairIt != Rhs.PairIt; } FORCEINLINE ItKeyType& Key() const { return PairIt->Key; } FORCEINLINE ItValueType& Value() const { return PairIt->Value; } FORCEINLINE PairType& operator* () const { return *PairIt; } FORCEINLINE PairType* operator->() const { return &*PairIt; } protected: PairItType PairIt; }; /** The base type of iterators that iterate over the values associated with a specified key. */ template class TBaseKeyIterator { private: typedef typename TChooseClass::Result SetItType; typedef typename TChooseClass::Result ItKeyType; typedef typename TChooseClass::Result ItValueType; public: /** Initialization constructor. */ FORCEINLINE TBaseKeyIterator(const SetItType& InSetIt) : SetIt(InSetIt) { } FORCEINLINE TBaseKeyIterator& operator++() { ++SetIt; return *this; } /** conversion to "bool" returning true if the iterator is valid. */ FORCEINLINE explicit operator bool() const { return !!SetIt; } /** inverse of the "bool" operator */ FORCEINLINE bool operator !() const { return !(bool)*this; } FORCEINLINE ItKeyType& Key() const { return SetIt->Key; } FORCEINLINE ItValueType& Value() const { return SetIt->Value; } protected: SetItType SetIt; }; /** A set of the key-value pairs in the map. */ ElementSetType Pairs; public: /** Map iterator. */ class TIterator : public TBaseIterator { public: /** Initialization constructor. */ FORCEINLINE TIterator(TMapBase& InMap, bool bInRequiresRehashOnRemoval = false) : TBaseIterator(InMap.Pairs.CreateIterator()) , Map(InMap) , bElementsHaveBeenRemoved(false) , bRequiresRehashOnRemoval(bInRequiresRehashOnRemoval) { } /** Destructor. */ FORCEINLINE ~TIterator() { if (bElementsHaveBeenRemoved && bRequiresRehashOnRemoval) { Map.Pairs.Relax(); } } /** Removes the current pair from the map. */ FORCEINLINE void RemoveCurrent() { TBaseIterator::PairIt.RemoveCurrent(); bElementsHaveBeenRemoved = true; } private: TMapBase& Map; bool bElementsHaveBeenRemoved; bool bRequiresRehashOnRemoval; }; /** Const map iterator. */ class TConstIterator : public TBaseIterator { public: FORCEINLINE TConstIterator(const TMapBase& InMap) : TBaseIterator(InMap.Pairs.CreateConstIterator()) { } }; using TRangedForIterator = TBaseIterator; using TRangedForConstIterator = TBaseIterator; /** Iterates over values associated with a specified key in a const map. */ class TConstKeyIterator : public TBaseKeyIterator { public: FORCEINLINE TConstKeyIterator(const TMapBase& InMap, KeyInitType InKey) : TBaseKeyIterator(typename ElementSetType::TConstKeyIterator(InMap.Pairs, InKey)) {} }; /** Iterates over values associated with a specified key in a map. */ class TKeyIterator : public TBaseKeyIterator { public: FORCEINLINE TKeyIterator(TMapBase& InMap, KeyInitType InKey) : TBaseKeyIterator(typename ElementSetType::TKeyIterator(InMap.Pairs, InKey)) {} /** Removes the current key-value pair from the map. */ FORCEINLINE void RemoveCurrent() { TBaseKeyIterator::SetIt.RemoveCurrent(); } }; /** Creates an iterator over all the pairs in this map */ FORCEINLINE TIterator CreateIterator() { return TIterator(*this); } /** Creates a const iterator over all the pairs in this map */ FORCEINLINE TConstIterator CreateConstIterator() const { return TConstIterator(*this); } /** Creates an iterator over the values associated with a specified key in a map */ FORCEINLINE TKeyIterator CreateKeyIterator(KeyInitType InKey) { return TKeyIterator(*this, InKey); } /** Creates a const iterator over the values associated with a specified key in a map */ FORCEINLINE TConstKeyIterator CreateConstKeyIterator(KeyInitType InKey) const { return TConstKeyIterator(*this, InKey); } FORCEINLINE ValueType* Find(KeyConstPointerType Key) { if (auto* Pair = Pairs.Find(Key)) { return &Pair->Value; } return nullptr; } FORCEINLINE const ValueType& FindChecked(KeyConstPointerType Key) const { const auto* Pair = Pairs.Find(Key); // check(Pair != nullptr); return Pair->Value; } /** * Find a reference to the value associated with a specified key. * * @param Key The key to search for. * @return The value associated with the specified key, or triggers an assertion if the key does not exist. */ FORCEINLINE ValueType& FindChecked(KeyConstPointerType Key) { auto* Pair = Pairs.Find(Key); // check(Pair != nullptr); return Pair->Value; } FORCEINLINE ValueType FindRef(KeyConstPointerType Key) const { if (const auto* Pair = Pairs.Find(Key)) { return Pair->Value; } return ValueType(); } FORCEINLINE int32 Num() const { return Pairs.Num(); } private: /** * DO NOT USE DIRECTLY * STL-like iterators to enable range-based for loop support. */ FORCEINLINE friend TRangedForIterator begin(TMapBase& MapBase) { return TRangedForIterator(begin(MapBase.Pairs)); } FORCEINLINE friend TRangedForConstIterator begin(const TMapBase& MapBase) { return TRangedForConstIterator(begin(MapBase.Pairs)); } FORCEINLINE friend TRangedForIterator end(TMapBase& MapBase) { return TRangedForIterator(end(MapBase.Pairs)); } FORCEINLINE friend TRangedForConstIterator end(const TMapBase& MapBase) { return TRangedForConstIterator(end(MapBase.Pairs)); } }; template class TSortableMapBase : public TMapBase { // friend struct TContainerTraits; protected: typedef TMapBase Super; TSortableMapBase() = default; TSortableMapBase(TSortableMapBase&&) = default; TSortableMapBase(const TSortableMapBase&) = default; TSortableMapBase& operator=(TSortableMapBase&&) = default; TSortableMapBase& operator=(const TSortableMapBase&) = default; }; template> class TMap : public TSortableMapBase { public: typedef TSortableMapBase Super; typedef typename Super::KeyInitType KeyInitType; typedef typename Super::KeyConstPointerType KeyConstPointerType; typedef TPair ElementType; public: typedef TSet ElementSetType; public: TMap() = default; TMap(TMap&&) = default; TMap(const TMap&) = default; TMap& operator=(TMap&&) = default; TMap& operator=(const TMap&) = default; };