std::unordered_map std::map 自定义类型键名

198次阅读
没有评论

共计 1026 个字符,预计需要花费 3 分钟才能阅读完成。

一句话总结

std::unordered_map std::map 自定义类型键名

map 需要重载小于号, unordered_map 需要重载== 比较

map 和 unordered_map 都需要特化 std::hash

std::hash 里面就一个小括号重载, 返回结构计算处理的哈希值

struct MAP_KEY
{
    int         i;          // 结构的成员....
    PAINTSTRUCT ps;         // 可以是复杂类型
    std::vector<int> arr;   // 也可以是对象

    // 这个是 map 使用, 比较本结构是否比传递进来的结构小
    bool operator<(const MAP_KEY& p) const
    {
        return i < p.i;
    }

    // 这个是 unordered_map 使用, 比较本结构和传递进来的结构是否是一样
    bool operator==(const MAP_KEY& p) const
    {
        return ps.hdc == p.ps.hdc &&
            memcmp(&ps.rcPaint, &p.ps.rcPaint, sizeof(ps.rcPaint)) == 0;
    }
};
template <> struct std::hash<MAP_KEY>
{
    _NODISCARD size_t operator()(const MAP_KEY& _Keyval) const noexcept
    {
        // 这里返回结构计算的哈希值, 如果结构是普通类型
        // 可以使用 std::_Fnv1a_append_value() 来计算哈希值
        // 
        // 是复杂类型的, 需要自行计算, 比如现在这个结构有vector
        // 数组内容可能会增删, 所以不把数组内容加入到计算哈希中
        // 这里演示直接 把ps成员 和 i 成员分别计算然后异或
        return std::_Fnv1a_append_value(std::_FNV_offset_basis, _Keyval.ps) ^
            std::_Fnv1a_append_value(std::_FNV_offset_basis, _Keyval.i);

        // 或者 std::is_trivial_v<> 的值是false的时候
        // 而且自己知道结构里除了没有默认构造函数之外没有其他东西
        // 那可以直接调用 std::_Fnv1a_append_bytes() 来计算
        // 直接把本结构的每个字节拿出来计算哈希
        return std::_Fnv1a_append_bytes(std::_FNV_offset_basis,
                                        &reinterpret_cast<const unsigned char&>(_Keyval),
                                        sizeof(_Keyval));
    }
};

正文完
 0
评论(没有评论)