Hash & EqualTo функции для unordered_set <BSTR> - PullRequest
0 голосов
/ 01 апреля 2019

В коде, который вставляет OLE-строки в стиле Windows (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 на самом деле не являются BSTR строками (которые сохраняют свои длина в слове памяти, непосредственно предшествующем данным BSTR, и wstring s сохраняют их длину где-нибудь еще).

Вопрос : Какие функции Hash и EqualTo из библиотеки STL подойдут для unordered_map<BSTR> в этом случае?

P.S. Конечно, я мог бы развернуть свои собственные функции, но я предпочитаю свернуть что-то уже в стандарте.

1 Ответ

3 голосов
/ 01 апреля 2019

Проблема с использованием 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;
...