Reputation: 6943
I often need a container where an hash is associated to an arbitrary object (collisions are theoretically possible if two different objects have the same hash).
In C++98 I would use template<class Key, class T> class std::map
using Key
as the hash computed on T
:
struct object;
typedef std::string object_hash;
object_hash compute_hash(const object& obj);
std::map<object_hash, object> hash_map;
object_hash insert_or_assign(const object& obj)
{
object_hash hash = compute_hash(obj);
hash_map[hash] = obj;
return hash;
}
std::pair<bool, object> get_at(const object_hash& hash)
{
std::map<object_hash, object>::iterator iter = hash_map.find(hash);
if( iter == hash_map.end() )
return std::pair<bool, object>(false, object());
else
return std::pair<bool, object>(true, iter->second);
}
But starting from C++11 we have hashed containers so I expected something like:
template<class T, class Key = std::hash<T>> class std::hashed_map
with the requirement to provide a custom std::hash
for type T
, but instead we have
template<class Key, class T, class Hash = std::hash<Key>> class unordered_map
which does not apply to my scenario where the key is the hash itself, and there is no other "key" concept related to the arbitrary object.
Similar to what I expected is:
template<class Key, class Hash = std::hash<Key>> class unordered_set
but there are no lookup functions based on hash.
In modern C++ is there a built in container that uses hashes and has a lookup interfaces based on these hashes?
Upvotes: 1
Views: 1645
Reputation: 1072
Originally the unordered_map
was called hash_map
, then the ISO C++ committee wisely renamed it, because the important difference between std::map
and std::unordered_map
is not that the first uses binary trees while the latter uses hashes, but that the first is ordered while the latter guarantees constant-time complexity.
So the fact that std::unordered_map
uses hashes internally is little more than an implementation detail: you only need to provide an std::hash
specialization if the key is a custom type (and the key is unfrequently a custom type). Apart from that, you should forget about the internal hashes of this container.
Despite some comments, if your key is the hash then there’s absolutely nothing wrong with you C++98 implementation. You can keep using it in C++ >= 11, updating and tiding it to the new language facilities where possible.
Upvotes: 2
Reputation: 275878
You have a map not a hash map; the fact your key is a hash is irrelevant to the container.
About the only salient feature is that you rarely care about the order of hashes; so unordered map is probably best.
Take your old solution, replace map with unordered map, replace less
operstion with equal
and a hash (possibly down) to 64 bits. For example, the classic pointer hash is just reinterpret_cast<unit_ptr>( key )
.
Upvotes: 2