亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在無序容器中將std :: hash <Key> :: operator()專用于用戶定義類型?

如何在無序容器中將std :: hash <Key> :: operator()專用于用戶定義類型?

C++
慕容3067478 2019-10-09 16:45:01
為了支持用戶定義的鍵類型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> 使用type 的默認哈希值編寫將更方便X,例如與編譯器和庫一起提供的類型。經過咨詢C ++標準草案N3242§20.8.12 [unord.hash]和§17.6.3.4[hash.requirements],增強無序g ++ include\c++\4.7.0\bits\functional_hash.hVC10 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標準?有便攜式的方法嗎?
查看完整描述

3 回答

?
守候你守候我

TA貢獻1802條經驗 獲得超10個贊

明確允許并鼓勵您向名稱空間* 添加特殊化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。)


*)我想,只要其中一種涉及類型是用戶定義的即可。


查看完整回答
反對 回復 2019-10-09
?
慕俠2389804

TA貢獻1719條經驗 獲得超6個贊

我的賭注將放在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

}

當然


hashX可能也是一個全局靜態函數

在第二種情況下,您可以通過

老式仿函數對象(struct Xhasher { size_t operator(const X&) const; };)

std::hash<X>()

任何滿足簽名的綁定表達式-


查看完整回答
反對 回復 2019-10-09
?
繁星淼淼

TA貢獻1775條經驗 獲得超11個贊

涵蓋了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。


查看完整回答
反對 回復 2019-10-09
  • 3 回答
  • 0 關注
  • 853 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號