It seems as if C++ does not have a hash function for strings in the standard library. Is this true?
What is a working example of using a string as a key in an unordered_
I ran into this today (actually with wstring
, not string
, but it's the same deal): using wstring
as a key in an unordered_map
generates an error about no hash function being available for that type.
The solution for me was to add:
#include <string>
Believe it or not, without the #include
directive I still had the wstring
type available but apparently NOT the ancillary functions like the hash. Simply adding the include above fixed it.
Actually, there is std::hash<std::string>
But there it is how you can use another hash function:
struct StringHasher {
size_t operator()(const std::string& t) const {
//calculate hash here.
}
}
unordered_map<std::string, ValueType, StringHasher>
In my case it was really distraction.
I had a type X for which I implemented hashing for const& X an utilized it somewhere with
std::unordered_map<const X, int> m_map;
Then I wanted to have another map which key are of the type X
and did:
std::unordered_map<X, int> map_x;
Notice the LACK of const
on the second case.
If you have a CustomType
and you want to plug into the STL infrastructure this is what you could do.
namespace std
{
//namespace tr1
//{
// Specializations for unordered containers
template <>
struct hash<CustomType> : public unary_function<CustomType, size_t>
{
size_t operator()(const CustomType& value) const
{
return 0;
}
};
//} // namespace tr1
template <>
struct equal_to<CustomType> : public unary_function<CustomType, bool>
{
bool operator()(const CustomType& x, const CustomType& y) const
{
return false;
}
};
} // namespace std
If you then want to create say a std::unordered_map<CustomType>
the STL will find the hash
and equal_to
functions without you having to do anything more with the template. This is how I like to write my custom equality comparer that support unordered data structures.
C++ STL provides template specializations of std::hash
for the various string classes. You could just specify std::string
as key type for std::unordered_map
:
#include <string>
#include <unordered_map>
int main()
{
std::unordered_map<std::string, int> map;
map["string"] = 10;
return 0;
}