52

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_map that will work with any c++ compiler?

5
  • 3
    I'm curious what gave you the idea that the standard library (at least a library that supported unordered_map) didn't support a hash function for std::string? Commented Mar 24, 2013 at 7:05
  • 1
    "error C2338: The C++ Standard doesn't provide a hash for this type." when I try to use string. Commented Mar 24, 2013 at 7:28
  • 1
    Perhaps this SO answer might be related to what's happening to you: stackoverflow.com/a/11157019/12711 Are you using basic_string<> directly instead of through the std:string typedef? You might be able to use basic_string<> for some purposes without a compiler error because another header happens to be pulling in xstring (which gives you basic_string<>, but not std::hash<string>) Commented Mar 24, 2013 at 8:11
  • 6
    So the bottom line is - make sure you have a #include <string> if you're trying to use strings in an unordered_map<> - actually, any time you're using std::string. Unfortunately, the compiler will sometimes let you get away without the include because of side effects from other includes. then when you add a use that actually requires the string header you get a mysterious, non-obvious error from the compiler. Commented Mar 24, 2013 at 8:15
  • What happens to me sometimes is the IDE incorrectly change my #include <unordered_map> to #include <bits/unordered_map.h>. So make sure you have included the correct lib. Commented Jun 7, 2017 at 22:03

5 Answers 5

42

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;
}
Sign up to request clarification or add additional context in comments.

4 Comments

This is the implicit behavior from the type constructor, is it not? Specifying std::hash<std::string>> when you already have an std::unordered_map<std::string> is just redundant.
I think this should be compiled with option "-std=c++0x"?
@Bloodmoon, Yes (I'd say, with -std=c++11), unordered_map is a C++11 feature.
JohnLeidegren is right, but for learners, the explicit code might be helpful: std::unordered_map<std::string, int, std::hash<std::string>> map; (the original answer before editing). Here, std::hash<std::string> can be omitted because std::unordered_map is defined as template<class Key, class T, class Hash=std::hash<Key>, ...> class unordered_map;.
28

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.

1 Comment

This answer most directly addressed my issue (not including <string>)
17

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>

Comments

8

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.

1 Comment

Note: unary_function is deprecated. Better to provide the typedefs result_type and argument_type yourself.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.