在UE4中,TMap是一個比較常用的容器购裙,TMap的用法很簡單,本文將著重介紹一下TMap如何自定義結(jié)構(gòu)體鍵值。
和眾多Map容器的實現(xiàn)方法類似坯台,TMap也是通過將Key轉(zhuǎn)換為Hash,來建立對Value的索引瘫寝,故而想要建立自定義結(jié)構(gòu)體的Key蜒蕾,勢必要確保其可順利轉(zhuǎn)換為Value。下面是UE4中TMap中關(guān)于創(chuàng)建Hash的相關(guān)代碼:
/** Defines how the map's pairs are hashed. */
template<typename KeyType, typename ValueType, bool bInAllowDuplicateKeys>
struct TDefaultMapKeyFuncs : BaseKeyFuncs<TPair<KeyType,ValueType>,KeyType,bInAllowDuplicateKeys>
{
typedef typename TTypeTraits<KeyType>::ConstPointerType KeyInitType;
typedef const TPairInitializer<typename TTypeTraits<KeyType>::ConstInitType, typename TTypeTraits<ValueType>::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);
}
};
其中GetSetKey()用于設(shè)置Key的值焕阿,Matches()用于進(jìn)行Key值碰撞測試咪啡,GetTypeHash()用于獲取Key的Hash。根據(jù)以上代碼不難發(fā)現(xiàn)捣鲸,在生成Hash的時候會會調(diào)用Key值結(jié)構(gòu)體的“==”運(yùn)算符來判斷兩個Key值是否相等瑟匆,以及GetTypeHash()來產(chǎn)生Hash,由此我們可以得到第一種構(gòu)建自定義結(jié)構(gòu)體鍵值的方法:
struct FMyKey
{
FString Name;
FString Type;
FORCEINLINE friend bool operator==(const FMyKey& Lhs, const FMyKey& Rhs)
{
return (Lhs.Name == Rhs.Name) && (Lhs.Type == Rhs.Type);
}
};
/** Case insensitive string hash function. */
FORCEINLINE uint32 GetTypeHash(const FMyKey& Key)
{
return HashCombine(GetTypeHash(Key.Name), GetTypeHash(Key.Type));
}
該方法相當(dāng)于是寫了Key結(jié)構(gòu)體的“==”運(yùn)算符函數(shù)和GetTypeHash函數(shù)栽惶,它們均為全局函數(shù)愁溜,這樣可以通過我們定義好的全局函數(shù)來生成Hash。
第二種方式就是定義自己的MapKeyFuncs來替代TDefaultMapKeyFuncs外厂,代碼如下:
struct FMyStruct
{
// String which identifies our key
FString UniqueID;
// Some state which doesn't affect struct identity
float SomeFloat;
explicit FMyStruct(float InFloat)
:UniqueID(FGuid::NewGuid().ToString())
, SomeFloat(InFloat)
{
}
};
template <typename ValueType>
struct TMyStructMapKeyFuncs :
BaseKeyFuncs<
TPair<FMyStruct, ValueType>,
FString
>
{
private:
typedef BaseKeyFuncs<
TPair<FMyStruct, ValueType>,
FString
> Super;
public:
typedef typename Super::ElementInitType ElementInitType;
typedef typename Super::KeyInitType KeyInitType;
static KeyInitType GetSetKey(ElementInitType Element)
{
return Element.Key.UniqueID;
}
static bool Matches(KeyInitType A, KeyInitType B)
{
return A.Compare(B, ESearchCase::CaseSensitive) == 0;
}
static uint32 GetKeyHash(KeyInitType Key)
{
return FCrc::StrCrc32(*Key);
}
};
TMap<
FMyStruct,
int32,
FDefaultSetAllocator,
TMyStructMapKeyFuncs<int32>
> MyMapToInt32;
以上是自己在UE4的學(xué)習(xí)中總結(jié)的兩種構(gòu)造自定義結(jié)構(gòu)體鍵值的方法冕象,希望對大家能有所幫助。
和眾多Map容器的實現(xiàn)方法類似汁蝶,TMap也是通過將Key轉(zhuǎn)換為Hash渐扮,來建立對Value的索引,故而想要建立自定義結(jié)構(gòu)體的Key掖棉,勢必要確保其可順利轉(zhuǎn)換為Value墓律。下面是UE4中TMap中關(guān)于創(chuàng)建Hash的相關(guān)代碼:
/** Defines how the map's pairs are hashed. */
template<typename KeyType, typename ValueType, bool bInAllowDuplicateKeys>
struct TDefaultMapKeyFuncs : BaseKeyFuncs<TPair<KeyType,ValueType>,KeyType,bInAllowDuplicateKeys>
{
typedef typename TTypeTraits<KeyType>::ConstPointerType KeyInitType;
typedef const TPairInitializer<typename TTypeTraits<KeyType>::ConstInitType, typename TTypeTraits<ValueType>::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);
}
};
其中GetSetKey()用于設(shè)置Key的值,Matches()用于進(jìn)行Key值碰撞測試幔亥,GetTypeHash()用于獲取Key的Hash耻讽。根據(jù)以上代碼不難發(fā)現(xiàn),在生成Hash的時候會會調(diào)用Key值結(jié)構(gòu)體的“==”運(yùn)算符來判斷兩個Key值是否相等帕棉,以及GetTypeHash()來產(chǎn)生Hash针肥,由此我們可以得到第一種構(gòu)建自定義結(jié)構(gòu)體鍵值的方法:
struct FMyKey
{
FString Name;
FString Type;
FORCEINLINE friend bool operator==(const FMyKey& Lhs, const FMyKey& Rhs)
{
return (Lhs.Name == Rhs.Name) && (Lhs.Type == Rhs.Type);
}
};
/** Case insensitive string hash function. */
FORCEINLINE uint32 GetTypeHash(const FMyKey& Key)
{
return HashCombine(GetTypeHash(Key.Name), GetTypeHash(Key.Type));
}
該方法相當(dāng)于是寫了Key結(jié)構(gòu)體的“==”運(yùn)算符函數(shù)和GetTypeHash函數(shù)饼记,它們均為全局函數(shù),這樣可以通過我們定義好的全局函數(shù)來生成Hash慰枕。
第二種方式就是定義自己的MapKeyFuncs來替代TDefaultMapKeyFuncs具则,代碼如下:
struct FMyStruct
{
// String which identifies our key
FString UniqueID;
// Some state which doesn't affect struct identity
float SomeFloat;
explicit FMyStruct(float InFloat)
:UniqueID(FGuid::NewGuid().ToString())
, SomeFloat(InFloat)
{
}
};
template <typename ValueType>
struct TMyStructMapKeyFuncs :
BaseKeyFuncs<
TPair<FMyStruct, ValueType>,
FString
>
{
private:
typedef BaseKeyFuncs<
TPair<FMyStruct, ValueType>,
FString
> Super;
public:
typedef typename Super::ElementInitType ElementInitType;
typedef typename Super::KeyInitType KeyInitType;
static KeyInitType GetSetKey(ElementInitType Element)
{
return Element.Key.UniqueID;
}
static bool Matches(KeyInitType A, KeyInitType B)
{
return A.Compare(B, ESearchCase::CaseSensitive) == 0;
}
static uint32 GetKeyHash(KeyInitType Key)
{
return FCrc::StrCrc32(*Key);
}
};
TMap<
FMyStruct,
int32,
FDefaultSetAllocator,
TMyStructMapKeyFuncs<int32>
> MyMapToInt32;
以上是自己在UE4的學(xué)習(xí)中總結(jié)的兩種構(gòu)造自定義結(jié)構(gòu)體鍵值的方法,希望對大家能有所幫助具帮。
參考文獻(xiàn):https://www.cnblogs.com/pengyingh/articles/5647879.html