支持在
std :: unordered_set<Key>
和std :: unordered_map<Key,Value>
中使用用户定义的键类型,
需要提供operator ==(Key,Key)
和一个哈希函数:struct X { int id; /* ... */ };
bool operator==(X a, X b) { return a.id == b.id; }
struct MyHash {
size_t operator()(const X& x) const { return std::hash<int>()(x.id); }
};
std::unordered_set<X, MyHash> s;
写成 std::unordered_set<X>
并使用类型X
的默认哈希函数,就像使用编译器和库提供的类型那样,会更方便。在查阅以下内容之后:
- C++标准草案N3242 §20.8.12 [unord.hash] 和 §17.6.3.4 [hash.requirements],
- Boost.Unordered
- g++
include\c++\4.7.0\bits\functional_hash.h
- VC10
include\xfunctional
- Stack Overflow上的各种相关问题
似乎可以专门为std::hash<X>::operator()
进行特化:
namespace std { // argh!
template <>
inline size_t
hash<X>::operator()(const X& x) const { return hash<int>()(x.id); } // works for MS VC10, but not for g++
// or
// hash<X>::operator()(X x) const { return hash<int>()(x.id); } // works for g++ 4.7, but not for VC10
}
考虑到对于C++11的编译器支持仍然是实验性质的(我没有尝试过Clang),这些是我的问题:
在命名空间
std
中添加这样的特化是否合法?我对此有不同的看法。如果有的话,哪个版本的
std::hash<X>::operator()
符合C++11标准?有一种便携式的方法可以做到吗?
operator==(const Key, const Key)
。 - Victor Lyuboslavskystd::hash
的特化(与std
命名空间中的其他内容不同)受到Google样式指南的反对;请谨慎使用。 - Franklin Yu