在代码中,将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库中的wstring
和Hash
函数适合EqualTo
吗?
P.S。当然,我可以推出自己的函数,但是我更喜欢包装标准中已经存在的东西。
答案 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;