Почему std::hash структура вместо функции?
Стандартная библиотека реализует std:: hash как шаблонную структуру, которая специализируется для разных типов. Используется так:
#include <iostream>
#include <functional>
int main()
{
std::hash<int> hasher;
std::cout << hasher(1337) << std::endl;
return 0;
}
Мой вопрос заключается в том, что является причиной этого выбора дизайна. Почему это не реализовано как шаблонная функция и не используется так:
#include <iostream>
#include <functional>
int main()
{
std::cout << std::hash<int>(1337) << std::endl;
return 0;
}
2 ответа
Решение
Есть несколько причин, каждая из которых достаточно хороша для выбора:
- Вы можете частично специализировать шаблоны классов, но вы можете только полностью специализированные шаблоны функций (по крайней мере, пока). Таким образом, вы можете обеспечить замену всего набора связанных аргументов шаблона с помощью
std::hash<T>
будучи шаблоном класса. Обратите внимание, что частичная перегрузка не помогает, потому что хэш-функцию нужно как-то указывать как объект, который нельзя сделать с помощью перегруженных функций (если они не доступны через объект, но это то, что отличается от них). - Неупорядоченные ассоциативные контейнеры параметризуются с помощью статической сущности (которую также можно динамически настраивать, если это поддерживает конкретный тип), что проще сделать с помощью шаблонов классов.
- Поскольку объекты, используемые для хэш-функции, можно настраивать, выбор между использованием типа или указателя функции для настройки. Указатели на функции часто трудно встроить, в то время как встроенные функции-члены типа тривиальны для встроенных, что значительно повышает производительность простых функций, таких как вычисление простого хеша.
Функция шаблона не может быть частично специализированной для типов, в то время как std::hash
специализированный для разных типов в качестве шаблона класса.
И таким способом, основанным на классах шаблонов, вы можете выполнять метапрограммирование, например, доступ к типу возвращаемого значения и типу ключа, как показано ниже:
std::hash<X>::argument_type
std::hash<X>::result_type