Thank you for your answer. The link to the universal hashing wikipedia page was enlightening.
I digged myself a deep hole searching for hash code implementations. Here's what I found:
* Division based hash codes are simple to implement but requires the table size to be a prime number.
* Multiplication based hash codes don't require the table size to be a prime number.
* Certain factors are better than others when using multiplicative hashing.
* There's a bit of folklore surrounding hash functions. Dan Bernsteins djb2 has been popular for a long time but few people understand why the constants are selected as they are. The PNV hash code is another simple algorithm that is easy to implement but that few understand.
* Multiply-shift hash codes is a recent (1997) invention.
* In later years CityHash, MurmurHash and SpookyHash has been developed. They are complicated compared to the earlier hash codes.
* Dan Bernstein created SipHash which is supposed to be immune (or atleast more resistant) to DOS attacks against hash tables.
As for hashing pointers, the GNU libstdc++ library just casts the pointer to an int value
. I wonder how they get around the bias introduced by alignment and memory allocated in arenas?