2013-11-24 1 views
16

Стандартная библиотека реализует std :: hash как структуру шаблона, которая специализирована для разных типов. Он используется следующим образом:Почему std :: hash struct вместо функции?

#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; 
} 
+0

2 примера идентичны, единственное отличие состоит в том, что во втором объект не указан. – user2485710

+0

Неопределенные ассоциированные контейнеры имеют параметр типа шаблона для указания хэша; это позволяет использовать объекты хэш-объекта с сохранением состояния (например, используя специальное значение, которое XORed на хэше). Получение типа специализированной функции шаблона не имеет сильного синтаксиса. – dyp

+1

@ user2485710 Первый пример компилируется, второй - нет. Второй должен быть записан как «std :: hash () (1337)» для использования неназванной временной структуры. – hvd

ответ

16

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

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

Чтобы быть справедливым, хэш-значение по умолчанию могло вызывать функцию, которая тогда могла бы для не поддерживаемых типов пытаться вызвать метод .hash() ', который позволял бы все вышеперечисленное, дать разрешить хэширование adl (что лучше, чем принудительное 'std' injection) и разрешить объектам self' hash', если они этого захотят. Но это нарушает KISS, хотя это соответствует тому, как работают «меньше» и «начинаются». – Yakk

4

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

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

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