Если вы не укажете свой собственный хеш-функтор в качестве аргумента шаблона, по умолчанию он будет равен std::hash<MyClass>
, которого не существует, если вы его не определите.
Лучше всего определить собственную специализацию std::hash
внутри пространства имен std
:
namespace std {
template <>
struct hash<MyClass>
{
typedef MyClass argument_type;
typedef std::size_t result_type;
result_type operator()(const MyClass & t) const
{
/* ..calculate hash value for t */
}
};
}
И убедитесь, что вы включили этот код перед объявлением вашего хэша. Таким образом, вы можете объявить хеш просто как std::unordered_set<MyClass>
без необходимости дополнительных аргументов шаблона.
Вы не указали, как выглядит MyClass
внутри, но типичная ситуация такова, что ваш определяемый пользователем тип просто состоит из нескольких членов простого типа, для которых существует хеш-функция по умолчанию. В этом случае вы, вероятно, захотите объединить хэш-значения для отдельных типов в хэш-значение для всей комбинации. Библиотека Boost предоставляет для этой цели функцию hash_combine
. Конечно, нет гарантии, что он будет хорошо работать в вашем конкретном случае (это зависит от распределения значений данных и вероятности коллизий), но он обеспечивает хорошую и простую в использовании отправную точку.
Вот пример того, как его использовать, предполагая, что MyClass
состоит из двух членов строки:
#include <unordered_set>
#include <boost/functional/hash.hpp>
struct MyClass
{
std::string _s1;
std::string _s2;
};
namespace std {
template <>
struct hash<MyClass>
{
typedef MyClass argument_type;
typedef std::size_t result_type;
result_type operator()(const MyClass & t) const
{
std::size_t val { 0 };
boost::hash_combine(val,t._s1);
boost::hash_combine(val,t._s2);
return val;
}
};
}
int main()
{
std::unordered_set<MyClass> s;
/* ... */
return 0;
}
person
jogojapan
schedule
21.11.2012