29

I've been switching my code over from std::map to std::unordered_map where appropriate. With std::map, I typically write the following just to make sure the key cannot be modified:

std::map<const std::string, int>

Frankly, I never checked if this const was of any value. This has always compiled and worked with g++.

Now, with std::unordered_map, the following fails to link with g++ 4.5.1.

std::unordered_map<const std::string, std::string> m;
m["foo"] = "bar";

with this link error:

Undefined symbols: "std::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const>::operator()(std::basic_string<char, std::char_traits<char>, std::allocator<char> >) const", referenced from:

The fix is simple, to remove const, but besides that, is there even a point in STL with any of the associative container classes to use a const key type? Are there no methods that let you get a reference to the key for any associative container?

2 Answers 2

28

The associative containers only expose the (key,value) pair as std::pair<const key_type, mapped_type>, so the additional const on the key type is superfluous.

Sign up to request clarification or add additional context in comments.

4 Comments

Or in other words: std::unordered_map<std::string, std::string> will do what he wants. (Says Jonathan, restating the obvious-to-most.)
Heh, yes, I can see how my answer requires looking at the original question to understand it :)
This makes so much sense. The things I struggle with in the morning. Thanks @MSN
This answer tells the asker, he does not need to do, what he was doing. The question, why he cannot do it, remains...
2

std::unordered_map<std::string const, std::string> uses std::hash<std::string const>, but no specialization exists for hash<std::string const>. However, there is one for std::hash<std::string>. You can provide one if you wish to use a std::string const as your key:

struct constant_string_hash {
    std::size_t operator () (std::string const &s) const {
        return hash<std::string>{}(s);
    }
};

You can then declare your std::unordered_map like this:

std::unordered_map<std::string const, std::string, constant_string_hash> m;
m["test key"] = "test value";

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.