14
votes

I want to use map in C++ STL to create assosiation between vector and int. But I got multiple compilation error with code presented below:

#include <vector>
#include <map>
#include <unordered_map>

using namespace std;

int main(void)
{
    unordered_map<vector<char>, int> mp;
    return 0;
}

And got this compilation error in VC++:

error C2280: 'std::hash<_Kty>::hash(const std::hash<_Kty> &)': attempting to reference a deleted function

However, if I change my code like presented below, then the code can be compiled properly:

#include <vector>
#include <map>
#include <unordered_map>

using namespace std;

int main(void)
{
    map<vector<char>, int> mp;
    return 0;
}

I have found this question asked in StackoverFlow, whose title is: C++ unordered_map using a custom class type as the key. But I wondered that why using map<> can pass the compilation check but unable with unordered_map<> ?

2
std::map uses strict weak ordering and by-defaultstd::less (which will implicitly by-default use some flavor of operator <). That is defined for vectors of comparable entities (such as char). std::unordered_map uses std::hash, and is not defined for your key type (std::vector<char>). So either define it or provide your own hashing override type.WhozCraig
Got this error value object do not have default constructor, has reference inside; end was a never ending loop ;-), now removing that reference.Tom

2 Answers

3
votes

Following on from @JohnZwinck's (excellent) answer, I would say that using std::unordered_map with a vector as a key is usually a bad idea, because of the likely high cost of implementing any kind of effective hashing function.

The link John gave expands on this, but, essentially, the hash function has to inspect every element in the vector every time anything needs to be hashed. If the vector is large, well, ouch!

So std::map is likely to be a better choice here, because std::less (-> operator<) is likely to be cheap - as soon as we hit an element of the vector whose value differs between the two operands, we are done. Worst case, it is no more expensive (although it's true that std::unordered_map is more efficient than std::map when a cheap and effective hashing function does exist, especially, for example, if the key is something like an int).

16
votes

map requires that less-than comparison is implemented. Which it is, for a vector. But unordered_map requires a hash function, which you'll need to implement yourself. It's not a big deal, you can see how to use hash_combine to do that here: Fast hash function for `std::vector`