С++ 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
специализации для ваших собственных типов, если они регулярны, а равенство транзитивно?
Ответы
Ответ 1
Да.
Если тип имеет следующие два свойства, я не думаю, что вы должны определить std::hash
:
-
Нет эффективного способа создания качественного хеша, который охватывает все данные, используемые для описания равенства.
-
Нет эффективного и/или интуитивного способа выбора согласованного подмножества данных для хеша.
Ответ 2
Предоставление специализации для собственных типов не имеет смысла, если они являются шаблонами классов,
поскольку хэш-функция (с высокой степенью вероятности) также зависит от
типы параметров шаблона, которые неизвестны.
Нет параметров шаблона, или параметры шаблона ограничены определенными типами
// 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>
.