1.. _More_on_HashCompare:
2
3More on HashCompare
4===================
5
6
7There are several ways to make the ``HashCompare`` argument for
8``concurrent_hash_map`` work for your own types.
9
10
11-  Specify the ``HashCompare`` argument explicitly
12
13
14-  Let the ``HashCompare`` default to ``tbb_hash_compare<Key>`` and do
15   one of the following:
16
17
18   -  Define a specialization of template ``tbb_hash_compare<Key>``.
19
20
21For example, if you have keys of type ``Foo``, and ``operator==`` is
22defined for ``Foo``, you just have to provide a definition of
23``tbb_hasher`` as shown below:
24
25
26::
27
28
29   size_t tbb_hasher(const Foo& f) {
30       size_t h = ...compute hash code for f...
31       return h;
32   };
33
34
35In general, the definition of ``tbb_hash_compare<Key>`` or
36``HashCompare`` must provide two signatures:
37
38
39-  A method ``hash`` that maps a ``Key`` to a ``size_t``
40
41
42-  A method ``equal`` that determines if two keys are equal
43
44
45The signatures go together in a single class because *if two keys are
46equal, then they must hash to the same value*, otherwise the hash table
47might not work. You could trivially meet this requirement by always
48hashing to ``0``, but that would cause tremendous inefficiency. Ideally,
49each key should hash to a different value, or at least the probability
50of two distinct keys hashing to the same value should be kept low.
51
52
53The methods of ``HashCompare`` should be ``static`` unless you need to
54have them behave differently for different instances. If so, then you
55should construct the ``concurrent_hash_map`` using the constructor that
56takes a ``HashCompare`` as a parameter. The following example is a
57variation on an earlier example with instance-dependent methods. The
58instance performs both case-sensitive or case-insensitive hashing, and
59comparison, depending upon an internal flag ``ignore_case``.
60
61
62::
63
64
65   // Structure that defines hashing and comparison operations
66   class VariantHashCompare {
67       // If true, then case of letters is ignored.
68       bool ignore_case;
69   public:
70       size_t hash(const string& x) const {
71           size_t h = 0;
72           for(const char* s = x.c_str(); *s; s++)
73               h = (h*16777179)^*(ignore_case?tolower(*s):*s);
74           return h;
75       }
76       // True if strings are equal
77       bool equal(const string& x, const string& y) const {
78           if( ignore_case )
79               strcasecmp(x.c_str(), y.c_str())==0;
80           else
81               return x==y;
82       }
83       VariantHashCompare(bool ignore_case_) : ignore_case(ignore_case_) {}
84   };
85    
86
87   typedef concurrent_hash_map<string,int, VariantHashCompare> VariantStringTable;
88    
89
90   VariantStringTable CaseSensitiveTable(VariantHashCompare(false));
91   VariantStringTable CaseInsensitiveTable(VariantHashCompare(true));
92