1. ホーム
  2. c++

[解決済み] std::hash<Key>::operator() をユーザー定義型に特化させる方法は?

2022-10-05 02:56:27

質問

でユーザー定義のキータイプをサポートするために 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 , のように、コンパイラやライブラリと一緒に提供されるタイプのためのものです。 相談した結果

を特殊化することが可能なようです。 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を試したわけではありません。

  1. このような特殊化を名前空間 std ? 私はそれについて複雑な気持ちです。

  2. のうち、どれが std::hash<X>::operator() のバージョンは、C++11 標準に準拠していますか?

  3. ポータブルな方法はありますか?

どのように解決するのですか?

を追加することが明示的に許可され、推奨されています。 特殊化 を名前空間 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_tostd::swap .)

*) 関係する型の1つがユーザー定義である限りは、そうでしょう。