When learning data structures, specifically hashtables, we were told that inventing an effective hash function to a datatype is a very hard task, but it was suggested that a quick shortcut exists. Namely, if we can assume that objects do not move around in memory, and we can define object equality as having the same memory address (use reference equality as opposed to value equality), then we can obtain the hashcode of an object like this:
#include<iostream>
template<typename T>
class hashcoder {
private:
union impl {
T* ptr;
int32_t hashcode; // or int64_t on a 64-bit architecture = architecture with 64-bit pointers
};
public:
static int32_t hash(const T& r) {
impl i;
i.ptr = &r;
return i.hashcode;
}
};
class myclass {
// whatever
};
int main() {
myclass m;
std::cout << hashcoder<myclass>::hash(m) << std::endl;
}
So my question is:
- Is there anything wrong with using memory address for hashcode (again assuming reference equality is the desired behaviour)?
- Given that using unions for conversion is undefined behaviour, how can we convert a memory address to an integer?
- (Feel free to point out any other errors I've made in the above code. C++ pointers are dangerously easy to get wrong.)