このunordered_map<pair<int, int>, *Foo>
のようなunordered_mapを定義する必要がありますが、hash
関数とequal
関数を定義してこのマップに渡すための構文は何ですか?
私はそれにこのオブジェクトを渡そうとしました:
class pairHash{
public:
long operator()(const pair<int, int> &k) const{
return k.first * 100 + k.second;
}
};
そして運がない:
unordered_map<pair<int, int>, int> map = unordered_map<pair<int, int>, int>(1,
*(new pairHash()));
size_type_Buskets
が何を意味するのかわからないので、1
を付けました。それを行う正しい方法は何ですか?ありがとう。
これは、C++ 11では残念ながら省略されています。 Boostはhash_combine
の観点から答えを持っています。それらから貼り付けてください!ペアをハッシュする方法は次のとおりです。
template <class T>
inline void hash_combine(std::size_t & seed, const T & v)
{
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
namespace std
{
template<typename S, typename T> struct hash<pair<S, T>>
{
inline size_t operator()(const pair<S, T> & v) const
{
size_t seed = 0;
::hash_combine(seed, v.first);
::hash_combine(seed, v.second);
return seed;
}
};
}
タプルや範囲など、他の多くのものの基礎としてhash_combine
を使用できるため、たとえば、各メンバーが個別にハッシュ可能である限り、(順序付けられた)コンテナー全体をハッシュできます。
これで、新しいマップを宣言できます。
std::unordered_map<std::pair<int, int>, my_mapped_type> mymap;
自作のハッシャー(優れた統計プロパティを持っていない)を使用する場合は、テンプレートパラメーターを明示的に指定する必要があります。
std::unordered_map<std::pair<int,int>, int, pairHash> yourmap;
デフォルトではデフォルトで作成されるため、ハッシュオブジェクトのコピーを指定する必要はないことに注意してください。
Boostの使用に問題がない場合、よりクリーンな解決策は、Boostのペアのハッシュ関数の実装に依存することです(実際、kerrek-sbが彼の回答で説明していることを正確に実行します)。したがって、あなたがしなければならないのは:
#include <unordered_map>
#include <boost/functional/hash.hpp>
using namespace std;
using namespace boost;
unordered_map<pair<int, int>, int, hash<pair<int, int>>> table;
ハッシュ関数の戻り値の型は、long
ではなくsize_t
である必要があります(ただし、これはエラーの原因ではありません)。カスタムハッシュ関数を提供するために示した構文が正しくありません。
上記を適切に機能させるには、同等の述語も提供する必要があります。
#include <unordered_map>
#include <utility>
using namespace std;
class pairHash{
public:
size_t operator()(const pair<int, int> &k) const{
return k.first * 100 + k.second;
}
};
struct pairEquals : binary_function<const pair<int,int>&, const pair<int,int>&, bool> {
result_type operator()( first_argument_type lhs, second_argument_type rhs ) const
{
return (lhs.first == rhs.first) && (lhs.second == rhs.second);
}
};
int main()
{
unordered_map<pair<int, int>, int, pairHash, pairEquals> myMap;
myMap[make_pair(10,20)] = 100;
myMap.insert( make_pair(make_pair(100,200), 1000) );
}
編集:operator==
はstd::pair
に対して定義されており、pairEquals
で行ったことを正確に実行するため、等しい述語を定義する必要はありません。比較が異なる方法で行われることを期待する場合にのみ、pairEquals
定義が必要になります。