I have a specialization of std::basic_string
, say, string_t
, and it the same as std::string
except that the third template argument is my custom allocator.
std::basic_string<>
Question: How should I define a hash functor class for this specialization using hash functors already provided in C++ standard library?
I know how to define a Hash functor, but I don't know how to utilize existing std::hash<..>
functors in std
to define my custom one. I hesitate to write my own hashing operations, knowing it is reinventing the wheel and is unlikely to be better than std::hash<std::string>
, since the only difference between string_t
and std::string
is just the allocator.
cppreference has some examples but they don't help me much - I don't want to construct a temporarystd::string
object using my string_t
object's c_str()
method only to feed the temporary object into std::hash<std::string>
to get the hash value, because it entails allocating temporary heap memory.
I'm using C++14 and I want to stick to standard library.
The idea is to make each cell of hash table point to a linked list of records that have same hash function value. Let's create a hash function, such that our hash table has 'N' number of buckets. To insert a node into the hash table, we need to find the hash index for the given key.
std::hash<const char*> produces a hash of the value of the pointer (the memory address), it does not examine the contents of any character array.
That means you can only have 256 unique hashes of arbitrary inputs. Since you can definitely create more than 256 different strings, there is no way the hash would be unique for all possible strings.
Since C++11, C++ has provided a std::hash< string >( string ) . That is likely to be an efficient hashing function that provides a good distribution of hash-codes for most strings.
Question: How should I define a hash functor class for this specialization using hash functors already provided in C++ standard library?
The short and sad answer is that there is no way to do this. The standard library does not offer hash functions for sequences of integral types.
boost::hash
is superior in every way to std::hash
. I would suggest you define your std::hash
specialisation in terms of it.
Furthermore, if you can, specify boost::hash<>
as the hashing function for all unordered containers. You'll never regret it. std::hash
is a half-formed library.
#include <string>
#include <cassert>
#include <unordered_set>
#include <boost/functional/hash.hpp>
struct my_alloc ...
using my_string = std::basic_string<char, std::char_traits<char>, my_alloc>;
std::size_t hash_value(::my_string const& s)
{
return boost::hash_range(s.begin(), s.end());
}
namespace std {
template<> struct hash<::my_string>
{
std::size_t operator()(::my_string const& s) const
{
return hash_value(s);
}
};
}
int main()
{
auto x = my_string("Hello");
using Set1 = std::unordered_set<my_string, boost::hash<my_string>>;
auto set1 = Set1 { x };
auto h = std::hash<my_string>();
auto hh = h(x);
assert(hh == hash_value(x));
return int(hh);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With