Unordered_map с пользовательскими хэшированием/равными функциями - функции не вызываются

Это странно.. следующий код (который мне удалось скомпилировать благодаря Cassio Neri) компилируется без каких-либо ошибок.. кстати, либо hashing_func, либо key_equal_func do call call (выходы не отображаются в окне консоли)

#include <iostream>
#include <string>
#include <unordered_map>
#include <algorithm>
#include <functional>

using namespace std;

unsigned long hashing_func(string key)
{
    cout << "Hashing called";
    unsigned long hash = 0;
    for(int i=0; i<key.size(); i++)
    {
        hash += (71*hash + key[i]) % 5;
    }
    return hash;
}

template<class T> bool key_equal_fn(T t1, T t2)
{
    return t1 == t2;
}

template <> bool key_equal_fn<string>(string t1, string t2)
{
    cout << "Equal called";
    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> &)(function<bool(string,string)>(key_equal_fn<string>))) ;

    bool case_insensitive = mymap.key_eq()("test","TEST");

    mymap["paul"] = "jenna";
    mymap["frank"] = "ashley";

    if(mymap["paul"] == mymap["frank"])
        cout << "equal" << endl;


    return 0;
}

Я использую MSVC2012, любой намек на то, что может быть проблемой?

Ответ 1

Проблема в том, что вам нужно передать типы вашей хеш-функции и функции hash_key_equal на ваш unordered_map, а затем фактические функции для ctor карты.

Ваше определение unordered_map должно выглядеть следующим образом:

unordered_map<
    std::string,
    std::string,
    std::function<unsigned long(std::string)>,
    std::function<bool(std::string, std::string)>
> mymap(n, hashing_func, key_equal_fn<std::string>);

unordered_map является шаблоном и выглядит следующим образом:

template<
    class Key,
    class T,
    class Hash = std::hash<Key>,
    class KeyEqual = std::equal_to<Key>,
    class Allocator = std::allocator<std::pair<const Key, T>>
> class unordered_map;

что означает, что если вы хотите передать новые функции Hash и KeyEqual, вы должны указать шаблону типы этих вещей.

Ссылка больше не доступна (запрос обновления): Живой пример

Ответ 2

Вы должны указать функции hash/compare с аргументами шаблона, а не в конструкторе. Вот пример:

class Hasher
{
public:
  size_t operator() (string const& key) const
  {
      cout << "Hashing called";
      size_t hash = 0;
      for(size_t i=0; i<key.size(); i++)
      {
          hash += (71*hash + key[i]) % 5;
      }
      return hash;
  }
};
class EqualFn
{
public:
  bool operator() (string const& t1, string const& t2) const
  {
    cout << "Equal called";
    return !(t1.compare(t2));
  }
};

unordered_map<string, string, Hasher, EqualFn> mymap(5);