Hash和EqualTo函数用于unordered_set <bstr>

时间:2019-04-01 19:58:51

标签: c++ windows stl c++17

在代码中,将Windows样式的OLE字符串(BSTR插入到良好的STL容器-unordered_map<BSTR>中,我声明了unordered_set,如下所示:

unordered_set<BSTR, std::hash<std::wstring>, std::equal_to<std::wstring>> usetBstr;

期望BSTR字符串起到wstring的作用。

一切似乎都可以正常工作,直到有一天BSTR放在字符串中间的wchar处都为unordered_set

当然!,当编译器将BSTR转换为std::wstring时,它将在字符串中找到的第一个空终止符处停止,因为wstring并不是真正的{{ 1}}字符串(将其长度保留在BSTR数据之前的存储字中,而BSTR的长度保留在其他位置)。

问题:在这种情况下,STL库中的wstringHash函数适合EqualTo吗?

P.S。当然,我可以推出自己的函数,但是我更喜欢包装标准中已经存在的东西。

1 个答案:

答案 0 :(得分:3)

使用std::hash<std::wstring>std::equal_to<std::wstring>的问题在于,当编译器将BSTR转换为std::wstring时,它会在字符串中找到的第一个空终止符处停止。这意味着"this\0\0""this\0"在散列并检查是否相等时变成相同的字符串。

您需要提供一个适配器,该适配器将正确的构造std::wstring / std::wstring_view传递给哈希和相等函数。您可以通过创建自己的函子(例如

struct BSTR_hash
{
    std::size_t operator()(BSTR const& s) const noexcept
    {
        return std::hash<std::wstring_view>{}({s, SysStringLen(s)});
    }
};
struct BSTR_equal_to
{
    bool operator()(BSTR const& lhs, BSTR const& rhs) const noexcept
    {
        return std::wstring_view(lhs, SysStringLen(lhs)) == std::wstring_view(rhs, SysStringLen(rhs));
    }
};

unordered_set<BSTR, BSTR_hash, BSTR_equal_to> usetBstr;