[英]How to specialize std::hash<Key>::operator() for user-defined type in unordered containers?
要在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;
只編寫帶有類型X
的默認散列的std::unordered_set<X>
會更方便,就像編譯器和庫附帶的類型一樣。 咨詢后
include\\c++\\4.7.0\\bits\\functional_hash.h
include\\xfunctional
似乎可以專門化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 標准?
有沒有便攜的方法來做到這一點?
明確允許並鼓勵您向命名空間std
* 添加專業化。 添加哈希函數的正確(並且基本上是唯一的)方法是:
namespace std {
template <> struct hash<Foo>
{
size_t operator()(const Foo & x) const
{
/* your code here, e.g. "return hash<int>()(x.value);" */
}
};
}
(您可能考慮支持的其他流行專業化是std::less
、 std::equal_to
和std::swap
。)
*) 只要涉及的類型之一是用戶定義的,我想。
我的賭注是 unordered_map/unorder_set/... 類的 Hash 模板參數:
#include <unordered_set>
#include <functional>
struct X
{
int x, y;
std::size_t gethash() const { return (x*39)^y; }
};
typedef std::unordered_set<X, std::size_t(*)(const X&)> Xunset;
typedef std::unordered_set<X, std::function<std::size_t(const X&)> > Xunset2;
int main()
{
auto hashX = [](const X&x) { return x.gethash(); };
Xunset my_set (0, hashX);
Xunset2 my_set2(0, hashX); // if you prefer a more flexible set typedef
}
當然
struct Xhasher { size_t operator(const X&) const; };
)std::hash<X>()
@Kerrek SB 已經涵蓋了 1) 和 3)。
2) 盡管 g++ 和 VC10 聲明std::hash<T>::operator()
具有不同的簽名,但兩個庫實現都符合標准。
標准沒有指定std::hash<T>
的成員。 它只是說每個這樣的特化必須滿足std::unordered_set
等的第二個模板參數所需的相同“哈希”要求。 即:
H
是一個函數對象,至少有一個參數類型Key
。H
是可復制構造的。H
是可破壞的。h
是H
或const H
類型的表達式,並且k
是可轉換為(可能是const
) Key
的類型的表達式,則h(k)
是類型為size_t
的有效表達式。h
是H
或const H
類型的表達式,而u
是Key
類型的左值,則h(u)
是類型為size_t
不會修改u
的有效表達式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.