Reputation: 3
Let's take unordered_set for example.
The default predicate for determining if two elements are equal is std::equal_to<T>(t1,t2)
,
which is simply t1==t2
.
Now lets suppose that for this T type I've implemented operator==()
so that not all member variables are part of this comparison, i.e two different T elements t1,t2 can be equal on comparison.
If the underlying hashtable calculates a different hash for each of these t1 and t2, when does it even perform the t1==t2
check for duplication of keys? and if there are more checks, how does it stay constant-time on average?
Upvotes: 0
Views: 105
Reputation: 238331
If the underlying hashtable calculates a different hash for each of these t1 and t2, when does it even perform the t1==t2 check for duplication of keys?
When the hash function causes newly inserted element to be placed into a non-empty bucket. Comparison will be made between pre-existing elements in that bucket to ensure uniqueness.
how does it stay constant-time on average?
By assuming that the hash function distributes random keys into the buckets evenly, and by increasing the number of buckets as the number of elements grows.
how could std::hash know how i implement openrator==()
Whoever writes the specialisation of std::hash for your class must know how you implement operator==.
The hash function must produce same hash for all elements that compare equal. If it doesn't, then the behaviour of the program will be undefined. Standard refs: [unord.req], [defns.required.behavior]
Upvotes: 1
Reputation: 16670
I think the key point that you're missing is that you supply two functors to the unordered container, and they have to work together.
There's the hash function, which calculates a number from an object.
There's a comparison function, which compares two objects for "equivalence".
As @Eljay said in his comment, for two objects that compare "equivalent" (the comparison function returns true
), the hash function must return the same value.
If your functions do not provide this guarantee, then the containers will not work correctly.
std::unordered_set: Meets the requirements of UnorderedAssociativeContainer.
UnorderedAssociativeContainer: are parameterized by Key/Hash/Pred.
With the requriement:
* If two Keys are equal according to Pred.
* Hash must return the same value for both keys.
Upvotes: 5
Reputation: 30494
The unordered associateive containers require that any two keys that compare equal also have the same hash. From [unord.req]:
The container's object of type
Hash
— denoted byhash
— is called the hash function of the container. The container's object of typePred
— denoted bypred
— is called the key equality predicate of the container.Two values
k1
andk2
are considered equivalent if the container's key equality predicatepred(k1, k2)
is valid and returnstrue
when passed those values. Ifk1
andk2
are equivalent, the container's hash function shall return the same value for both.
Your operator==
and std::hash
implementations must be consistent. If they are not then you have not fulfilled the prerequisites required to use your class as the key in an unordered associative container.
Upvotes: 1