Why isn't std::hash<const std::string> specialized in std?

Viewed 105

Why isn't std::hash<const std::string> specialized in std?

It causes compile error like

std::unordered_map<const std::string, int> m;
m.insert(std::make_pair("Foo", 1)); //error
m["Bar"] = 2; // also error

Is there any reason for this ?

1 Answers

Why isn't std::hash<const std::string> specialized in std?

In fact, std didn't specialize any std::hash<const T>. The reason is probably it's not needed. For any std::hash<T>, the only function it has is an operator(), which takes in const T& as it's argument. So even if std::hash<const Foo> was specialized, it would be exactly the same as std::hash<Foo>.

Then go back to the code you were troubling with, it really should've been instead:

std::unordered_map<std::string, int> m;

Here, despite the key_type is std::string, the actual type of the key is actually const std::string, which can be accessed with decltype(m)::value_type::first_type.


Update:

When you think of concept of hash, the key should not be changed, so specilaization of std::hash looks more appropriate than std::hash. Don't you agree ?

Sure the hash function does not and should not change the key, but in the same time, it probably shouldn't take a copy, so why not go for std::hash<const T&>?

One thing to note is that the type being specialized on does not always equal to the argument type. The template argument is more about what type the hash function is related to, not what is passed to the call operator. Similarly, numeric_limits<T> expect a non-cv qualified numeric type as type T. That doesn't mean const int and const double don't have their respective limits. Unless you are expecting different behaviors on hash<T> and hash<const T>, then why should you specialize them twice?

And one other thing to notice is that std::hash is really more of a utility class bundled with the unordered_XXX family, and is primarily used as the hash function for the unordered family defaultly, or used to define your custom hash function for your custom types to be supplied to the unordered family.

Related