Определение хеш-функции в TR1 unordered_map внутри структуры - PullRequest
4 голосов
/ 25 марта 2011

Согласно this , можно определить функцию равенства в TR1 unordered_map следующим образом:

#include <tr1/unordered_map>
using namespace std;
using namespace std::tr1;
struct foo{
    ...
    bool operator==(const foo& b) const{
        return ..;
    }
};

unordered_map<foo,int> map;

Можно ли определить хеш-функцию таким же образом?

Ответы [ 2 ]

12 голосов
/ 25 марта 2011

Если вы хотите изменить хеширование по умолчанию (или, чаще, обеспечить хеширование для типа, который в настоящее время не поддерживается), вы задаете специализацию std::tr1::hash<T> для своего типа ключа:

namespace std { 
namespace tr1 { 
    template<>
    struct hash<typename my_key_type> {
        std::size_t operator()(my_key_type const &key) {
            return whatever;
        }
    };
}
}

Обратите внимание, что специализация существующего шаблона для пользовательского типа является одним из редких случаев, когда вам конкретно разрешено писать код в namespace std.

1 голос
/ 25 марта 2011

Подпись класса unordered_map такова:

template<class Key,
    class Ty,
    class Hash = std::hash<Key>,
    class Pred = std::equal_to<Key>,
    class Alloc = std::allocator<std::pair<const Key, Ty> > >
    class unordered_map;

Ваш пример работает, потому что Pred по умолчанию, std :: equal_to <>, по умолчанию проверяет равенство, используя operator ==.Компилятор находит вашу функцию-член foo :: operator == и использует ее.

std :: hash не имеет никакой специализации, которая будет вызывать функцию-член в вашем классе, поэтому вы не можете просто добавитьчлен foo с пользовательским хешем.Вместо этого вам нужно будет специализировать std :: hash.Если вы хотите, чтобы это вызывало функцию-член на foo, продолжайте.Вы получите что-то вроде этого:

struct foo
{
    size_t hash() const
    {
       // hashing method here, return a size_t
    }
};

namespace std
{
    // Specialise std::hash for foo.
    template<>
    class hash< foo >
        : public unary_function< foo, size_t >
    {
    public:
        size_t operator()( const foo& f )
        {
            return f.hash();
        }
    };
}
...