我知道为通用的 std::tuple
专门定制 std::hash
是未定义行为。
但是,如果为特定的 tuple 定制 std::hash
呢?
例如,
namespace std {
template<>
struct hash<std::tuple<MyType, float>> {
size_t operator()(const std::tuple<MyType, float>& t) const {
// ...
}
};
}
甚至可以使用带有某种 required is_all_same_as_v<Ts…, MyType>
C++20 约束的std::tuple<Ts ...>
,以确保元组中的所有类型都完全等于MyType
。
例如,
namespace std {
template<typename... Ts>
requires (sizeof...(Ts) > 0 && is_all_same_as_v<Ts..., MyType>)
struct hash<std::tuple<Ts...>> {
size_t operator()(const std::tuple<Ts...>& t) const {
// ...
}
};
}
这仍然被认为是未定义的行为吗?如果是,为什么?
编辑:确保检查参数包的大小至少为1,以避免特化std::hash<std::tuple<>>
,这是绝对未定义的行为。
std
添加任何标准库类模板的模板专门化声明,前提是(a)所添加的声明依赖于至少一个程序定义的类型,且(b)该专门化满足原始模板的标准库要求。"hash<std::tuple<MyType, float>>"显然符合任何合理定义下"MyType"的依赖关系(标准似乎没有正式定义这种“依赖于”的关系;可能适用于依赖名称的规则)。 - Igor Tandetnikrequired is_all_same_as_v<Ts…, MyType>
是否会使模板“依赖于”MyType
。很可能是的,只要添加这样的特化不会干扰查找其他不提及MyType
的特化。 - Igor Tandetnik