整数对的哈希函数的错误

Sha*_*mbo 32 c++ hash stl unordered-map c++11

我有一个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 ;
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

但我收到以下错误:

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>’
Run Code Online (Sandbox Code Playgroud)

Cas*_*sey 46

不幸的是,这个程序有不确定的行为.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;
};
Run Code Online (Sandbox Code Playgroud)

编辑:我已经使用xor来结合这对成员的哈希值因为我很懒,但是为了认真使用xor是一个相当蹩脚的哈希组合函数.

  • 等等不仅stl没有为`std :: pair`s实现`std :: hash`,但它也不允许你自己实现它?为什么? (10认同)
  • (我对Jesse做了同样的评论)`std :: hash <T>()(x.first)^ std :: hash <T>()(x.second);` - 这是一种极易发生碰撞的哈希方式一对``,因为每对有两个相同的值哈希值为0,每对{a,b}哈希值与{b,a}相同.对于模糊要求的使用,更好地找到`hash_combine`函数并使用它. (7认同)
  • @Sidak存在一般规则,以防止用户干扰库实现者和/或将来对标准的更改.例如,库实现可以提供`std :: hash <std :: pair <T,U >>`的特化作为符合的扩展.或者C++ 35可能会定义这样的专业化.如果允许用户自己定义这样的专业化,那么两者都不可能 - 不破坏某些程序. (7认同)
  • @Casey,该死的!C++ 35 ......大约两十年了?那很苛刻...... :-) (3认同)
  • @Claudiu:您可以自己实现它,但前提是至少有一个模板参数是用户定义的类型. (2认同)
  • 您能否仅提供良好的哈希组合功能?:p (2认同)