(原文链接:https://abseil.io/tips/152 译者:clangpp@gmail.com)
每周贴士 #152: AbslHashValue和你
- 最初发布于2018-06-21
- 作者:Matt Kulukundis
(译者注:这库用起来就一个字儿,爽!)
“I love Mozart, but I often make a terrible hash of it.” – Simon Rattle
(译者注:译者文学水平太洼,起兴部分保留原文。欢迎在评论区提出翻译建议)
absl::Hash
框架现在是Swisstable家族哈希表(absl::{flat,node}hash{set,map}
)的默认哈希实现。所有能用这个框架计算哈希值的类型,都能自动用于Swisstable的键类型。
怎么用?
假设有个简单的结构体Song
(假设一个Song对象可以被以下数据成员唯一确定):
struct Song {
std::string name;
std::string artist;
absl::Duration duration;
};
然后想存一个absl::flat_hash_set<Song>
或absl::flat_hash_map<Song, CopyrightOwner>
。唯一需要做的事儿就是增加一个弱智的友元函数:
struct Song {
std::string name;
std::string artist;
absl::Duration duration;
template <typename H>
friend H AbslHashValue(H h, const Song& s) {
return H::combine(std::move(h), s.name, s.artist, s.duration);
}
// 为简洁起见,略去了==和!=操作符重载
};
齐活!
怎么测试?
我们提供了absl::VerifyTypeImplementsAbslHashCorrectly
来验证一个类型正确实现了(AbslHashValue()
的,译者注)重载。用这倒霉函数的时候有俩要求:
- 你的类型必须正确地实现了==操作符。
- 你得对你的类型所有可能的表达形式调用这个验证函数。(举个栗子,如果一个类型针对小数据进行了优化,那验证时就既要对小对象进行验证,又要对普通的对象进行验证。)
TEST(MyType, SupportsAbslHash) {
EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
MyType(),
MyType(1, 2),
MyType(2, 3),
MyType(0, 0),
}));
}
absl::VerifyTypeImplementsAbslHashCorrectly
同时也支持异构查找(简单说就是可以在std::set<std::string>
中查找const char*
,译者注)和自定义相等运算符(==)。
有点儿意思?想多了解点儿?扫一眼absl::Hash
的文档吧。