//
//
namespace std {
template <> //
struct hash
{
//
//
typedef size_t result_type;
typedef Sales_data argument_type; //
//
size_t operator()(const Sales_data& s) const;
//
//
};
size_t
hash
return hash
hash
hash
}
} //
//
Определение hash
начинается с части template<>
, означающей, что определяется полностью специализированный шаблон. Специализируемый шаблон называется hash
, а специализированная версия — hash
. Члены класса следуют непосредственно из требований для специализации шаблона hash
.
Подобно любым другим классам, специализируемые члены можно определить в классе или вне его, как это сделано здесь. Перегруженный оператор вызова должен определять хеш-функцию по значениям заданного типа. Эта функция обязана возвращать каждый раз тот же результат, когда она вызывается для данного значения. Хеш-функция практически всегда возвращает другой результат для не равных объектов.
Все сложности определения хорошей хеш-функции делегируем библиотеке. Библиотека определяет специализации класса hash
для встроенных типов и для большинства библиотечных типов. Безымянный объект hash
используется для создания хеш-кода для переменной-члена bookNo
, объект типа hash
для создания хеш-кода из переменной-члена units_sold
и объекта типа hash
для создания хеш-кода из переменной-члена revenue. Применение к этим результатам оператора исключающего ИЛИ (см. раздел 4.8) сформирует общий хеш-код для заданного объекта класса Sales_data
.
Следует заметить, что хеш-функция определена для хеширования всех трех переменных-членов, чтобы она была совместима с определением оператора operator==
класса Sales_data
(см. раздел 14.3.1). По умолчанию неупорядоченные контейнеры используют специализацию хеша, соответствующую типу key_type
, наряду с оператором равенства типа ключа.
С учетом того, что специализация находится в области видимости, она будет использоваться автоматически при использовании класса Sales_data
как ключ в одном из этих контейнеров:
//
//
unordered_multiset
Поскольку hash
использует закрытые члены класса Sales_data
, этот класс следует сделать другом класса Sales_data
:
template
//
class Sales_data {
friend class std::hash
//
};
Здесь указано, что специфический экземпляр hash
является дружественным. Поскольку данный экземпляр определяется в пространстве имен std
, следует помнить, что этот тип хеша определяется в пространстве имен std
. Следовательно, объявление friend
относится к std::hash
.
Sales_data
использовать специализацию шаблона hash
, следует определить эту специализацию в заголовке Sales_data
.
В отличие от шаблона функции, специализация шаблона класса не обязана предоставлять аргументы для каждого параметра шаблона. Можно определить некоторые из них, но не все.