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