Специализация std::hash для шаблонного ключа
Я пытался специализировать хеш для своего собственного типа, шаблонного ключа.
Я основывал это на cppreference.
Я получаю ошибку компиляции "Стандарт C++ не предоставляет хэш для этого типа". Я полагаю, я просто сделал это неправильно. Может ли компилятор даже поддерживать такой шаблон?
namespace std {
template<typename SType, typename AType, typename PType>
struct MyKey {
const SType from;
const AType consume;
const PType pop;
};
template<typename SType, typename AType, typename PType>
struct hash<MyKey<SType, AType, PType>> {
size_t operator ()(MyKey const &key) {
std::hash<SType>()(key.from);
std::hash<AType>()(key.consume);
std::hash<PType>()(key.pop);
}
};
}
1 ответ
Есть несколько проблем с вашим кодом:
Вам не разрешено размещать новые определения или объявления в std
Пространство имен; только специализации (такие как std::hash
) разрешены. Так что ваши MyKey
шаблон должен быть удален из std
Пространство имен.
Ваш operator()
подпись неверна. MyKey
не называет тип, вам нужно явно его преобразовать. Кроме того, оператор должен быть отмечен const
,
std::hash
специализации должны предоставлять типы членов argument_type
а также result_type
,
Если не существует специализаций для типов, переданных как SType
и т.д., вы должны предоставить их сами.
Вы ничего не возвращаете из своей хеш-функции, просто вычисляете хеши других типов и выбрасываете их возвращаемые значения.
Реализация, которая будет компилироваться для типов, которые имеют свои собственные std::hash
специализация:
//moved out of std
template<typename SType, typename AType, typename PType>
struct MyKey {
const SType from;
const AType consume;
const PType pop;
};
namespace std {
template<typename SType, typename AType, typename PType>
struct hash<MyKey<SType, AType, PType>>{
//member types
using argument_type = MyKey<SType,AType,PType>;
//arguments specified ^ ^ ^
using result_type = std::size_t;
result_type operator ()(argument_type const& key) const {
//marked const ^
//these will fail if SType and friends don't have a std::hash specialization
result_type s_hash = std::hash<SType>()(key.from);
result_type a_hash = std::hash<AType>()(key.consume);
result_type p_hash = std::hash<PType>()(key.pop);
//in your actual code, you'll want to compute the return type from the above
return p_hash;
}
};
}