unordered_map
メンバーとpair<int,int>
に対して定義されたハッシュ関数を持つ次のクラスがあります
class abc
{public :
unordered_map < pair<int,int> , int > rules ;
unsigned nodes;
unsigned packet ;
};
namespace std {
template <>
class hash < std::pair< int,int> >{
public :
size_t operator()(const pair< int, int> &x ) const
{
size_t h = std::hash<int>()(x.first) ^ std::hash<int>()(x.second);
return h ;
}
};
}
しかし、私は次のエラーが発生しています:
error: invalid use of incomplete type ‘struct std::hash<std::pair<int, int> >
error: declaration of ‘struct std::hash<std::pair<int, int> >
error: type ‘std::__detail::_Hashtable_ebo_helper<1, std::hash<std::pair<int, int> >, true>’ is not a direct base of ‘std::__detail::_Hash_code_base<std::pair<int, int>, std::pair<const std::pair<int, int>, int>, std::__detail::_Select1st, std::hash<std::pair<int, int> >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, true>’
残念ながら、このプログラムには未定義の動作があります。 C++ 11§17.6.4.2.1:
プログラムは、宣言がユーザー定義型に依存し、その特殊化が元のテンプレートの標準ライブラリ要件を満たし、明示的に禁止されていない場合にのみ、標準ライブラリテンプレートのテンプレート特殊化を名前空間stdに追加できます。
hash<pair<int,int>>
は、プリミティブおよび標準ライブラリタイプのみに依存します。これは、名前空間std
の外部でハッシュクラスを定義し、マップ宣言でそのハッシュを明示的に使用することで簡単に回避できます。
struct pairhash {
public:
template <typename T, typename U>
std::size_t operator()(const std::pair<T, U> &x) const
{
return std::hash<T>()(x.first) ^ std::hash<U>()(x.second);
}
};
class abc {
std::unordered_map<std::pair<int,int>, int, pairhash> rules;
};
編集:私は怠け者なので、ここでペアメンバーのハッシュを結合するためにxorを使用しましたが、深刻な使用のために xorはかなりくだらないハッシュ結合関数です 。
std::hash<uintmax_t>
のコンポーネントのハッシュを混在させるには、std::pair
の標準実装に依存することを好みます。
#include <functional>
#include <utility>
struct hash_pair final {
template<class TFirst, class TSecond>
size_t operator()(const std::pair<TFirst, TSecond>& p) const noexcept {
uintmax_t hash = std::hash<TFirst>{}(p.first);
hash <<= sizeof(uintmax_t) * 4;
hash ^= std::hash<TSecond>{}(p.second);
return std::hash<uintmax_t>{}(hash);
}
};