int对的哈希函数出错

error for hash function of pair of ints

本文关键字:函数 出错 哈希 int      更新时间:2023-10-16

我有一个具有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);
    }
};