Search code examples
c++dictionaryhashmapprobingquadratic-probing

Different arguments with same template


I am trying to create a hashmap that uses a template. The template will take in a hash function (in the form of hash ( int key, int size ) ) and a probe function (in the form of probe ( int i ) in the case of probing and probe ( int key, int size ) in the case of a double hash. I hope you understand what I am saying. Here is my main:

#include "generic_map.h"

inline int hash( int key, std::size_t M ) { return key % M; }
inline int hash2( int key, std::size_t M ) { return key % (M-1) + 1; }
inline int linear_probe( int i ) { return i; }
inline int quadratic_probe( int i ) { return i*i; }


int main() {

    generic_map<int, char, int(*)(int,std::size_t), hash, int(*)(int), quadratic_probe, false> map1( 20);

generic_map<int, char, int(*)(int,std::size_t), hash, int(*)(int, std::size_t), hash2, true> map2( 20);

}

As you can see, I'm passing in two different pointer function types as the probe function. "Hash2" will be passed in as the probe function in the case of double hashing. Here is a snipper from my header file (namely my class declaration, node declaration, and insert method:

template <class KEY, class VALUE, class HASH_FUNC, HASH_FUNC hash, class PROBE_FUNC, PROBE_FUNC probe, bool double_hash>
//Hashmap Class
class generic_map {

private:

    //Node Class
    struct hashNode {

        KEY key;            //Stores the key of node
        VALUE value;         //Stores the value that associates to key

        hashNode(KEY key, VALUE &value) : key(key), value (value) {}   //hashNode constructor

    };

public:

//Creates a new backing array with user inserted capacity
    generic_map( int capacity ) {

        M = capacity;
        map = new hashNode * [capacity];

        for(int i = 0; i < M; ++i) {
            map[i] = NULL;
        }
    }

    //Deletes the hashNodes in the list and the map
    ~generic_map() {
        clear();
    }

    //If index that key hashes to is empty, insert. Else, replace value at hashed index.
    int insert( KEY key, VALUE value ) {

        int f = hash( key, M );
        int p = 0;
        int h = f;

        while( map[h] != NULL ) {

            if( p == M )
                return -1 * p;

            if( map[h]->key == key ) {
                map[h]->value = value;
                return p;
            }
            else {
                ++p;
                if(double_hash) {
                    h = f + (p * probe(key, M)) % M;
                }
                else {
                    h = f + (probe( p )) % M;     //This is throwing an error and will not compile, 
                }                                //saying, "too few arguments to function call.
            }
        }

The "else" part of the "double_hash_ condition in my insert method is flagging an error because I am of course calling the same probe, template function with two different argument numbers. I am not asking WHY it is throwing the error, as I already know why. I am asking for a solution to this - or a work around. Thanks.


Solution

  • Here are some solutions I can think about:

    1. A quick and dirty fix is to declare a dummy default second parameter, which will not be used, for the one-parameter probe functions, like

      inline int linear_probe( int i, int dummy = 0 ) { return i; }
      

      Now linear_probe has effectively 2 parameters, but one is initialized by default, so you'll be able to use a 2-parameter function pointer to point to it. But this solution is not the most elegant, probably you should think about changing your design. Why not make 2 separate classes, one for simple hashing, one for double? Or maybe make double hashing inherit from simple hashing.

    2. Use template specialization

      You need to specialize the class generic_map for true and false. Keep your generic definition, but just specialize the 2 versions like template<typename types (omit bool here as we specialize)> generic_map<types, true>. Take a look here for example: http://cprogramming.com/tutorial/template_specialization.html