I am in the process of writing my own map class. Currently the map accepts a key value in the form of a null-terminated string. This key is then converted in to a number using this hash function that I found online:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
const int Hash(const wchar_t *pstrString) const
{
long lHashValue{0};
wchar_t cKey{0};
int iIndex{0};
long lg{0};
cKey = pstrString[iIndex];
while (cKey != 0) {
lHashValue = (lHashValue << 4) + cKey;
lg = lHashValue & 0xF0000000L;
if (lg != 0) {
lHashValue ^= lg >> 24;
}
lHashValue &= ~lg;
cKey = pstrString[++iIndex];
}
return static_cast<int>(lHashValue);
}
|
I then use the
%
operator against the key and the dimension of a fixed-size array to determine the index where the the key/data pair is stored. All in all this technique seems to works well and I have a functional map class based upon it.
However, when I examine the STL/C++ standard library I find the map object implemented there will actually accept keys of
any type. I find this very puzzling and cannot work out how you would do this.
I can imagine a system where you can supply an
integer of any type to be hashed in to a key. I would do it by using a templated union where a fixed array of 8
unsigned char
elements share storage with the key material:
1 2 3 4 5
|
template<typename typeKey>
union uKEYMATERIAL{
typeKey TNumericKey;
unsigned char aucKey[8]
};
|
I would then feed the
aucKey
member into almost the same hash function as above, but specify it goes through the while loop only eight times--the maximum number of bytes used by c++ to store variable data (I think!).
However, I still don't see how you could accept a key of
any variable type... Perhaps you have to determine if the key is an array, pointer or integer using runtime-type-information?