C++ Hash Function Generator

Subscribe Send me a message home page


Enter class information


User Instruction

The first line is used to indicate the class name. The subsequent lines are used to define the fields used to construct the hash function (or the hasher object). The filed line must contain type and accessor attributes. The hasher attribute is optional. If the hasher is not specified, then the defualt std::hash will be used. Attributes in a field line are separated by ;.

Here is a sample:

Input:

class MyKey
    type = int; accessor = getValue();
    type = std::string; accessor = myString;
    type = Score; accessor = score; hasher = ScoreHasher;

Output:

namespace std {
    template<> struct hash<MyKey> {
        std::size_t operator()(const MyKey& obj) const {
            std::size_t v = std::hash<int>()(obj.getValue());
            hash_combine(v, std::hash<std::string>()(obj.myString));
            hash_combine(v, ScoreHasher()(obj.score));
            return v;
        }

        private:
        static void hash_combine(std::size_t& lhs, size_t rhs) {
            lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
        }
    };
}

struct MyKeyHasher {
    std::size_t operator()(const MyKey& obj) const {
        std::size_t v = std::hash<int>()(obj.getValue());
        hash_combine(v, std::hash<std::string>()(obj.myString));
        hash_combine(v, ScoreHasher()(obj.score));
        return v;
    }

    private:
    static void hash_combine(std::size_t& lhs, size_t rhs) {
        lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
    }
};

Testing

In this section, we will test the generated the hasher in the code. We need two customer-defined class: Score and MyKey and MyKey contains a Score field.

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <string>
#include <cstring>

class Score {
public:
    int numOfWins;
    Score(int numOfWins): numOfWins(numOfWins){};
};

struct ScoreHasher {

    std::size_t operator()(const Score& obj) const {
        std::size_t v = std::hash<int>()(obj.numOfWins) ;
        return v;
    }

    private:
    void hash_combine(std::size_t& lhs, size_t rhs) {
        lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
    }
};


class MyKey {
public:
    std::string myString;
    Score score;
    MyKey(std::string s, Score score, int value): myString(s), score(score), value(value){};
    int getValue() const {return this->value;}

private:
    int value;
};

namespace std {
    template<> struct hash<MyKey> {
        std::size_t operator()(const MyKey& obj) const {
            std::size_t v = std::hash<int>()(obj.getValue());
            hash_combine(v, std::hash<std::string>()(obj.myString));
            hash_combine(v, ScoreHasher()(obj.score));
            return v;
        }

        private:
        static void hash_combine(std::size_t& lhs, size_t rhs) {
            lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
        }
    };
}

struct MyKeyHasher {
    std::size_t operator()(const MyKey& obj) const {
        std::size_t v = std::hash<int>()(obj.getValue());
        hash_combine(v, std::hash<std::string>()(obj.myString));
        hash_combine(v, ScoreHasher()(obj.score));
        return v;
    }

    private:
    static void hash_combine(std::size_t& lhs, size_t rhs) {
        lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
    }
};

std::string toString(bool b) {
    return b ? "true" : "false";
}

int main() {
    Score score1{1};
    Score score2{2};

    std::string myString1{"mystring-1"};
    std::string myString2{"mystring-2"};

    int value1 = 1;
    int value2 = 2;

    std::cout << "ScoreHasher()(score1) == ScoreHasher()(Score{1}) => "
        << toString(ScoreHasher()(score1) == ScoreHasher()(Score{1})) << std::endl;

    std::cout << "ScoreHasher()(score1) == ScoreHasher()(score2) => "
        << toString(ScoreHasher()(score1) == ScoreHasher()(score2)) << std::endl;

    MyKey myKey1{myString1, score1, value1};
    MyKey myKey2{myString2, score2, value2};
    MyKey myKey3{myString2, score2, value1};

    std::cout << "std::hash<MyKey>()(myKey1) == MyKeyHasher()(myKey1) => "
        << toString(std::hash<MyKey>()(myKey1) == MyKeyHasher()(myKey1)) << std::endl;

    std::cout << "MyKeyHasher()(myKey1) = " << MyKeyHasher()(myKey1) << std::endl;
    std::cout << "MyKeyHasher()(myKey2) = " << MyKeyHasher()(myKey2) << std::endl;
    std::cout << "MyKeyHasher()(myKey3) = " << MyKeyHasher()(myKey3) << std::endl;
}

Here is the output

ScoreHasher()(score1) == ScoreHasher()(Score{1}) => true
ScoreHasher()(score1) == ScoreHasher()(score2) => false
std::hash<MyKey>()(myKey1) == MyKeyHasher()(myKey1) => true
MyKeyHasher()(myKey1) = 9868470674200887723
MyKeyHasher()(myKey2) = 9206230847985983005
MyKeyHasher()(myKey3) = 9206230847985978094

----- END -----

Send me a message Subscribe to blog updates

Want some fun stuff?

/static/shopping_demo.png


Comments