Search code examples
c++templateshashhash-function

How to implement the hash function for the various type of key?


I have implemented the hash map in C++. Everything works fine, except the hash function.

I have a template class of the element so that I can use various variable types for the hash map. Here is my code for the element.

template <class KeyType, class ValType>
class MapElem
{
public:
    typedef KeyType ktype;
    typedef ValType vtype;

    KeyType key;
    ValType val;

    MapElem* link;  // singly linked list
};

And the hashfunction code.

template <class HashMapElemType>
unsigned int 
HashMap<HashMapElemType>::hashfunction(const KeyType k)
{
    unsigned int hashIndex = 0;



    if (typeid(KeyType).name() == typeid(std::string).name())
    {
        unsigned int hashIndex = 0;

        const char* c = k.c_str();

        unsigned int i = 0;
        int index = 0;
        int shift = 0;

        while (c[index] != '\0')
        {
            if (shift == 32)
                shift = 0;
            i += ((int) c[index++]) << shift;
            shift += 8;
        }

        hashIndex = i;
    }
    else if (typeid(KeyType).name() == typeid(float).name())
    {   
        float f = k;
        hashIndex = (unsigned int) f;
    }
    else if (typeid(KeyType).name() == typeid(int).name())
    {
        int i = k;
        hashIndex = (unsigned int) i;
    }
    else
    {
        hashIndex = k;
    }

    hashIndex = hashIndex % divisor;

    return hashIndex;
}

And there is a compile error for type casting in the hashfunction. I understand why the error occurs, but I don't know how to fix it. I wonder how to get a hash value from different types of key value.

oh here is the error enter image description here


Solution

  • Your hash function should be a template function on the key type, implemented outside of your container class. You can then specialize the template function for each key type you're actually using the hash map with. This turns the type check from run-time to compile-time, making it both faster and safer.

    // hash function prototype, no implementation
    template<typename T> unsigned int CalculateHash( const T& v );
    
    // hash function specialization for std::string
    template<> unsigned int CalculateHash( const std::string& v )
    {
      // your hash function for std::string ...
    }
    

    Inside your container implementation you can then use the generic hash function to generate a hash value for your key.

    template <class HashMapElemType>
    unsigned int HashMap<HashMapElemType>::hashfunction(const KeyType& k)
    {
      // delegate to global hash function template
      return ::CalculateHash<KeyType>( k ); 
    }