将哈希函数定义为结构的一部分

Defining hash function as part of a struct

本文关键字:结构 一部分 定义 哈希 函数      更新时间:2023-10-16

我知道可以通过定义单独的哈希函数结构来定义 struct X的哈希函数:

struct hash_X {
    size_t operator()(const X &x) const {}
    bool operator()(const X &a, const X &b) const {}
};
int main() {
    unordered_set<X, hash_X, hash_X> s;
}

但是我正在寻找类似operator<的东西,可以将其附加到struct X本身,例如使用set

struct X {
    bool operator<(const X &other) const {}
};
int main() {
    set<X> s;
}

最终目标是:

struct X {
    size_t operator()(void) const {}
    bool operator()(const X &other) const {}
};
int main() {
    unordered_set<X> s;
}

这在C ?

中是否可以

std::unordered_setstd名称空间中定义。它使用std::hash结构来放置许多不同类型。如果您想能够使用std::unordered_set<X>(不在声明中添加太多信息),则必须创建另一个std::hash模板的过载,以使其成为您的结构 hash

您应该能够通过以下几个以下操作使其正常工作:

# include <unordered_set>
struct X {
    size_t operator()(void) const {}
    bool operator()(const X &other) const {}
};
namespace std {
    template<>
    struct hash<X> {
        inline size_t operator()(const X& x) const {
            // size_t value = your hash computations over x
            return value;
        }
    };
}
int main() {
    std::unordered_set<X> s;
}

andlo,您必须为您的结构提供对std::equal_to的过载或比较操作员(operator==())。您应该添加以下一项:

struct X {
    ...
    inline bool operator==(const X& other) const {
        // bool comparison = result of comparing 'this' to 'other'
        return comparison;
    }
};

或:

template <>
struct equal_to<X> {
    inline bool operator()(const X& a, const X& b) const {
        // bool comparison = result of comparing 'a' to 'b'
        return comparison;
    }
};

没有哈希运算符,但是您可以将hash结构隐藏在X的内部:

struct X
{
    std::string name;
    struct hash
    {
        auto operator()( const X& x ) const
        { return std::hash< std::string >()( x.name ); }
    };
};

您甚至可以成为朋友并将name私有化等。

实时示例

namespace hashing {
  template<class T>
  std::size_t hash(T const&t)->
  std::result_of_t<std::hash<T>(T const&)>
  {
    return std::hash<T>{}(t);
  }
  struch hasher {
    template<class T>
    std::size_t operator()(T const&t)const{
      return hash(t);
    }
  };
}

以上是设置基于ADL的hash系统的一些样板。

template<class T>
using un_set=std::unordered_set<T,hashing::hasher>;
template<class K, class V>
using un_map=std::unordered_map<K,V,hashing::hasher>;

现在创建了两个容器别名,您不必指定hasher。

添加新的哈希值:

struct Foo {
  std::string s;
  friend size_t hash(Foo const&f){
    return hashing::hasher{}(s);
  }
};

Fooun_setun_map中工作。

我会在hashing名称空间中添加对std容器和元组的支持(覆盖功能hash),并且神奇地将它们也起作用。

我建议考虑一个更通用的哈希类。您可以为此类定义所有可能需要的常见哈希操作操作:

struct ghash {
     // all the values and operations you need here 
}; 

然后,在要计算哈希的任何类中,您都可以定义转换操作员

struct X { 
    operator ghash () {  // conversion operator 
        ghash rh; 
        // compute the hash
        return rh; 
    }
};

然后,您可以轻松地计算哈希:

 X x; 
 ghash hx = x;   // convert x to a hash 
 hx = (ghash)x;  // or if you prefer to make it visible

这将使您更容易扩展您的哈希结构的使用,而无需重塑以后可能需要哈希的任何其他结构X,y,z。

在这里实时演示