I want to declare :
std::unordered_map<CString, CString> m_mapMyMap;
But when I build I got an error telling me that the standard C++ doesn't provide a hash function for CString, while CString have the (LPCSTR) operator.
How do I properly implement a hash function for CString?
Based on the MS STL implementation for std::string
I created the following methods which can be used for std::unordered_set
and 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)));
}
};
}
Or even more generic:
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)));
}
};
}
std::unordered_map use std::hash<> that does not use (LPCSTR)
operator.
You need to redefine hash function:
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;
But for better performance use std::string instead CString for key.
After trying out MrTux's suggestion , I have to say that this doesn't work anymore. std::_HashSeq
was removed and std::unary_function
was also removed in C++17.
I ended up with another solution that incorporates Microsoft's advice for hash implementations to use std::basic_string_view
's hasher:
namespace std
{
template<typename BaseType, class StringTraits>
struct hash<ATL::CStringT<BaseType, StringTraits>>
{
size_t operator()(const ATL::CStringT<BaseType, StringTraits>& key) const noexcept
{
return hash<basic_string_view<BaseType>>()(
basic_string_view<BaseType>(
key.GetString(),
key.GetLength()));
}
};
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.