Как реализовать хеш-функцию CString для использования с картой std::unordered?


Я хочу объявить :

std::unordered_map<CString, CString> m_mapMyMap;

Но при сборке я получил сообщение об ошибке, говорящее мне, что стандартный C++ не предоставляет хэш-функцию для CString, в то время как CString имеет оператор (LPCSTR).

Как правильно реализовать хэш-функцию для CString?

2 4

2 ответа:

Std:: unordered_map использует std:: hash, который не использует оператор (LPCSTR).

Вам нужно переопределить хэш-функцию:

template<class T> class MyHash;

template<>
class MyHash<CString> {
public:
    size_t operator()(const CString &s) const
    {
        return std::hash<std::string>()( (LPCSTR)s );
    }
};

std::unordered_map<CString,CString,MyHash> m_mapMyMap;

Но для лучшей производительности используйте std:: string вместо CString для ключа.

На основе реализации MS STL для std::string я создал следующие методы, которые могут быть использованы для std::unordered_set и std::unordered_map:

namespace std {
    template <>
    struct hash<CString>
    {   // hash functor for CString
        size_t operator()(const CString& _Keyval) const
        {   // hash _Keyval to size_t value by pseudorandomizing transform
            return (_Hash_seq((const unsigned char*)(LPCWSTR)_Keyval, _Keyval.GetLength() * sizeof(wchar_t)));
        }
    };

    template <>
    struct hash<CStringA>
    {   // hash functor for CStringA
        size_t operator()(const CStringA& _Keyval) const
        {   // hash _Keyval to size_t value by pseudorandomizing transform
            return (_Hash_seq((const unsigned char*)(LPCSTR)_Keyval, _Keyval.GetLength() * sizeof(char)));
        }
    };
}

Или еще более обобщенно:

namespace std {
    template<typename BaseType, class StringTraits>
    struct hash<CStringT<BaseType, StringTraits>> : public unary_function<CStringT<BaseType, StringTraits>, size_t>
    {   // hash functor for CStringT<BaseType, StringTraits>
        typedef CStringT<BaseType, StringTraits> _Kty;

        size_t operator()(const _Kty& _Keyval) const
        {   // hash _Keyval to size_t value by pseudorandomizing transform
            return (_Hash_seq((const unsigned char*)(StringTraits::PCXSTR)_Keyval,
                _Keyval.GetLength() * sizeof(BaseType)));
        }
    };
}