テンプレート引数として独自のハッシュファンクターを指定しない場合、デフォルトでになりますstd::hash<MyClass>
。これは、定義しない限り存在しません。
std::hash
内部名前空間の独自の専門分野を定義するのが最適std
です:
namespace std {
template <>
struct hash<MyClass>
{
typedef MyClass argument_type;
typedef std::size_t result_type;
result_type operator()(const MyClass & t) const
{
/* ..calculate hash value for t */
}
};
}
また、ハッシュを宣言する前に、必ずこのコードを含めてください。std::unordered_set<MyClass>
このようにして、テンプレート引数を追加する必要がないのと同じように、ハッシュを宣言できます。
内部の外観を指定しませんでしMyClass
たが、一般的な状況では、ユーザー定義型は、デフォルトのハッシュ関数が存在するいくつかの単純型メンバーで構成されています。この場合、個々のタイプのハッシュ値を組み合わせ全体のハッシュ値に結合することをお勧めします。Boostライブラリは、hash_combine
この目的のために呼び出される関数を提供します。もちろん、特定のケースでうまく機能するという保証はありませんが(データ値の分布と衝突の可能性によって異なります)、優れた使いやすい開始点を提供します。
MyClass
これは、2つの文字列メンバーで構成されていると仮定した場合の使用方法の例です。
#include <unordered_set>
#include <boost/functional/hash.hpp>
struct MyClass
{
std::string _s1;
std::string _s2;
};
namespace std {
template <>
struct hash<MyClass>
{
typedef MyClass argument_type;
typedef std::size_t result_type;
result_type operator()(const MyClass & t) const
{
std::size_t val { 0 };
boost::hash_combine(val,t._s1);
boost::hash_combine(val,t._s2);
return val;
}
};
}
int main()
{
std::unordered_set<MyClass> s;
/* ... */
return 0;
}