unordered_map constructor error (equal_to templated function)

c++, c++11

Solution

Both `hashing_func` and `key_equal_fn` should be functor objects (and not functions). In addition, their types must be provided to the `unordered_map` template, that is, the map should have this type:

unordered_map<string, string, hashing_func, key_equal_fn>

where `hashing_func` and `key_equal_fn` are functor classes:

struct hashing_func {
    unsigned long operator()(const string& key) const {
        unsigned long hash = 0;
        for(size_t i=0; i<key.size(); i++)
            hash += (71*hash + key[i]) % 5;
        return hash;
    }
};

struct key_equal_fn {
    bool operator()(const string& t1, const string& t2) const {
        return !(t1.compare(t2));
    }
};

Then, `mymap` is defined in this way:

typedef unordered_map<string, string, hashing_func, key_equal_fn> MapType;
MapType::size_type n = 5;
MapType mymap(n, hashing_func(), key_equal_fn());

Alternatively, `hashing_func` and/or `key_equal_fn` can be functions but you have to wrapp them into `std::function` objects. That is,

unsigned long hashing_func(const string& key) {
    unsigned long hash = 0;
    for(size_t i=0; i<key.size(); i++)
      hash += (71*hash + key[i]) % 5;
    return hash;
}

bool key_equal_fn(const string& t1, const string& t2){
  return !(t1.compare(t2));
}

and define `mymap` in this way

typedef unordered_map<string, string,
    std::function<unsigned long(const string&)>,
    std::function<bool(const string&, const string&)>> MapType;

MapType::size_type n = 5;
MapType mymap(n, hashing_func, key_equal_fn);

If you wish, you can use lambdas and refrain from writing the two funcions or functor classes:

typedef unordered_map<string, string,
    std::function<unsigned long(const string&)>,
    std::function<bool(const string&, const string&)>> MapType;

MapType mymap(n,
  [](const string& key) -> unsigned long {
      unsigned long hash = 0;
      for(size_t i=0; i<key.size(); i++)
        hash += (71*hash + key[i]) % 5;
      return hash;
  },
  [](const string& t1, const string& t2) {
       return !(t1.compare(t2));
  });

Finally, my favorite is an all-lambdas solution

auto hashing_func = [](const string& key) -> unsigned long {
    unsigned long hash = 0;
    for(size_t i=0; i<key.size(); i++)
        hash += (71*hash + key[i]) % 5;
    return hash;
};

auto key_equal_fn = [](const string& t1, const string& t2) {
    return !(t1.compare(t2));
};

typedef unordered_map<string, string,
    decltype(hashing_func), decltype(key_equal_fn)> MapType;

MapType::size_type n = 5;
MapType mymap(n, hashing_func, key_equal_fn);

Problem

I thought I could have a pointer to a fully-specialized template function, but the following code isn't compiling (MSVC2012) ``` #include <iostream> #include <string> #include <unordered_map> #include <algorithm> using namespace std; unsigned long hashing_func(string key) { unsigned long hash = 0; for(int i=0; i<key.size(); i++) { hash += (71*hash + key[i]) % 5; } return hash; } bool key_equal_fn2(string t1, string t2) { return t1 == t2; } template<class T> bool key_equal_fn(T t1, T t2) { return t1 == t2; } template <> bool key_equal_fn<string>(string t1, string t2) { return !(t1.compare(t2)); } int main () { unordered_map<string, string>::size_type n = 5; unordered_map<string, string> mymap(n, (const std::hash<string> &)hashing_func, (const std::equal_to<string> &)(key_equal_fn<string>)) ; mymap["paul"] = "jenna"; mymap["frank"] = "ashley"; return 0; } ``` The constructor line is returning the following error: error C2440: 'type cast' : cannot convert from 'bool (__cdecl *)(T,T)' to 'const std::equal_to<_Ty> &'

Original source