C++11: Существуют ли причины, по которым некоторые регулярные типы не должны специализировать `std::hash`?
Под Регулярным типом я подразумеваю определение Степанова в Элементах Программирования, в основном, что есть понятие равенства и что объекты, которые являются копиями друг друга, сравниваются равными.
Поэтому, когда у вас есть обычный тип T
и отношение равенства является транзитивным (a == b && b == c => a == c), вы можете определить (нетривиальную) хеш-функцию, которая согласуется с определением равенства (a == b = > h (a) == h (b)). Всегда.
Но стандарт не включает много std::hash
специализаций. Например std::complex
не имеет ни одного, и ни один из них не имеет контейнеров, за исключением vector<bool>
а также bitset
,
Поэтому мне интересно, каков принцип дизайна здесь.
Или спросили по-другому: есть ли причины не предоставлять std::hash
специализации для ваших собственных типов, при условии, что они регулярны и равенство транзитивно?
2 ответа
Да.
Когда тип имеет следующие два свойства, я не думаю, что вы должны определить std::hash
:
Не существует эффективного способа последовательно создать качественный хеш, который охватывает все данные, используемые для описания равенства.
Не существует эффективного и / или интуитивно понятного способа выбора согласованного подмножества данных для хеширования.
Предоставление специализации для собственных типов не имеет смысла, если они являются шаблонными классами, поскольку хеш-функция (с высокой и очень высокой вероятностью) также зависит от типов параметров шаблона, которые неизвестны.
Если нет никаких параметров шаблона, или параметры шаблона ограничены определенными типами
// provide no implementation to restrict all types
template<typename T> container;
// int is allowed
template<> container<int> {
...
}
// double is allowed
template<> container<double> {
...
}
обеспечение специализации std::hash
возможно, так как реализации классов (или экземпляров шаблонных классов) известны, как и для vector<bool>
вопреки complex<T>
,