UE4随笔——TMap自定义结构体键值

在UE4中,TMap是一个比较常用的容器,TMap的用法很简单,本文将着重介绍一下TMap如何自定义结构体键值。

UE4随笔——TMap自定义结构体键值_第1张图片
UE4随笔

和众多Map容器的实现方法类似,TMap也是通过将Key转换为Hash,来建立对Value的索引,故而想要建立自定义结构体的Key,势必要确保其可顺利转换为Value。下面是UE4中TMap中关于创建Hash的相关代码:

    /** Defines how the map's pairs are hashed. */
    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);
        }
    };

其中GetSetKey()用于设置Key的值,Matches()用于进行Key值碰撞测试,GetTypeHash()用于获取Key的Hash。根据以上代码不难发现,在生成Hash的时候会会调用Key值结构体的“==”运算符来判断两个Key值是否相等,以及GetTypeHash()来产生Hash,由此我们可以得到第一种构建自定义结构体键值的方法:

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));
}

该方法相当于是写了Key结构体的“==”运算符函数和GetTypeHash函数,它们均为全局函数,这样可以通过我们定义好的全局函数来生成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 
struct TMyStructMapKeyFuncs :
    BaseKeyFuncs<
    TPair,
    FString
    >
{
private:
    typedef BaseKeyFuncs<
        TPair,
        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
> MyMapToInt32;

以上是自己在UE4的学习中总结的两种构造自定义结构体键值的方法,希望对大家能有所帮助。

和众多Map容器的实现方法类似,TMap也是通过将Key转换为Hash,来建立对Value的索引,故而想要建立自定义结构体的Key,势必要确保其可顺利转换为Value。下面是UE4中TMap中关于创建Hash的相关代码:

    /** Defines how the map's pairs are hashed. */
    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);
        }
    };

其中GetSetKey()用于设置Key的值,Matches()用于进行Key值碰撞测试,GetTypeHash()用于获取Key的Hash。根据以上代码不难发现,在生成Hash的时候会会调用Key值结构体的“==”运算符来判断两个Key值是否相等,以及GetTypeHash()来产生Hash,由此我们可以得到第一种构建自定义结构体键值的方法:

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));
}

该方法相当于是写了Key结构体的“==”运算符函数和GetTypeHash函数,它们均为全局函数,这样可以通过我们定义好的全局函数来生成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 
struct TMyStructMapKeyFuncs :
    BaseKeyFuncs<
    TPair,
    FString
    >
{
private:
    typedef BaseKeyFuncs<
        TPair,
        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
> MyMapToInt32;

以上是自己在UE4的学习中总结的两种构造自定义结构体键值的方法,希望对大家能有所帮助。

参考文献:https://www.cnblogs.com/pengyingh/articles/5647879.html

你可能感兴趣的:(UE4随笔——TMap自定义结构体键值)