Хэш-функция unordered_map C++
Мне нужно определить unordered_map, как это unordered_map<pair<int, int>, *Foo>
какой синтаксис для определения и передачи hash
а также equal
функции к этой карте?
Я попытался передать ему этот объект:
class pairHash{
public:
long operator()(const pair<int, int> &k) const{
return k.first * 100 + k.second;
}
};
и не повезло
unordered_map<pair<int, int>, int> map = unordered_map<pair<int, int>, int>(1,
*(new pairHash()));
Я понятия не имею, что такое size_type_Buskets
значит, так что я дал 1
, Как правильно это сделать? Благодарю.
3 ответа
Это неудачное упущение в C++11; Boost имеет ответ с точки зрения hash_combine
, Не стесняйтесь просто вставить это от них! Вот как я хэш пар:
template <class T>
inline void hash_combine(std::size_t & seed, const T & v)
{
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
namespace std
{
template<typename S, typename T> struct hash<pair<S, T>>
{
inline size_t operator()(const pair<S, T> & v) const
{
size_t seed = 0;
::hash_combine(seed, v.first);
::hash_combine(seed, v.second);
return seed;
}
};
}
Ты можешь использовать hash_combine
в качестве основы для многих других вещей, таких как кортежи и диапазоны, чтобы вы могли хэшировать, например, весь (упорядоченный) контейнер, если каждый член может быть индивидуально хэшируемым.
Теперь вы можете просто объявить новую карту:
std::unordered_map<std::pair<int, int>, my_mapped_type> mymap;
Если вы хотите использовать ваш хэши доморощенного (у которого нет хороших статистических свойств), вы должны явно указать параметры шаблона:
std::unordered_map<std::pair<int,int>, int, pairHash> yourmap;
Обратите внимание, что нет необходимости указывать копию объекта-хеша, так как по умолчанию он создается по умолчанию.
Если вы в порядке с использованием Boost, более чистое решение состоит в том, чтобы полагаться на реализацию Boost хеш-функции для пар (которая фактически делает именно то, что Kerrek-SB объясняет в своем ответе). Поэтому все, что вам нужно сделать, это:
#include <unordered_map>
#include <boost/functional/hash.hpp>
using namespace std;
using namespace boost;
unordered_map<pair<int, int>, int, hash<pair<int, int>>> table;
Тип возвращаемого значения хэш-функции должен быть size_t
не long
(хотя это не является причиной ошибки). Синтаксис, который вы показали для предоставления пользовательской хэш-функции, неверен.
Вам также нужно будет предоставить равный предикат, чтобы все вышеперечисленное работало правильно.
#include <unordered_map>
#include <utility>
using namespace std;
class pairHash{
public:
size_t operator()(const pair<int, int> &k) const{
return k.first * 100 + k.second;
}
};
struct pairEquals : binary_function<const pair<int,int>&, const pair<int,int>&, bool> {
result_type operator()( first_argument_type lhs, second_argument_type rhs ) const
{
return (lhs.first == rhs.first) && (lhs.second == rhs.second);
}
};
int main()
{
unordered_map<pair<int, int>, int, pairHash, pairEquals> myMap;
myMap[make_pair(10,20)] = 100;
myMap.insert( make_pair(make_pair(100,200), 1000) );
}
РЕДАКТИРОВАТЬ:
Вам не нужно определять равный предикат, так как operator==
определяется для std::pair
и он делает именно то, что я сделал в pairEquals
, Вам понадобится только pairEquals
определение, если вы ожидаете, что сравнение будет сделано по-другому.