Почему std :: hash struct вместо функции?

Стандартная библиотека реализует 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;
}

Ответ 1

Есть несколько причин, каждый из которых достаточно хорош для выбора:

  1. Вы можете частично специализировать шаблоны классов, но вы можете только полностью специализированные шаблоны функций (по крайней мере, до сих пор). Таким образом, вы можете предоставить замену для целого набора связанных аргументов шаблона, когда std::hash<T> является шаблоном класса. Обратите внимание, что частичная перегрузка не помогает, потому что хеш-функцию нужно будет каким-то образом указать как объект, который нельзя сделать с перегруженными функциями (если только они не доступны через объект, а то, что отличается от него).
  2. Неупорядоченные ассоциативные контейнеры параметризуются статическим объектом (который также может быть настроен динамически, если конкретный тип поддерживает это), что упрощается с использованием шаблонов классов.
  3. Поскольку объекты, используемые для хеш-функции, настраиваются, выбор заключается в использовании указателя типа или функции для настройки. Указатели функций часто трудно встроить, в то время как встроенные функции-члены типа тривиальны для встроенных, что повышает производительность для простых функций, таких как простое вычисление простого хеша.

Ответ 2

Функция шаблона не может быть частично специализирована для типов, тогда как std::hash специализируется для разных типов в качестве шаблона класса.

И в этом шаблоне, основанном на шаблонах, вы можете выполнять мета-программирование, такое как доступ к типу возврата и типу ключа, как показано ниже:

std::hash<X>::argument_type
std::hash<X>::result_type