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

时间:2015-05-10 09:18:50

标签: c++

我知道通过定义一个单独的哈希函数struct可以为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 ++中是否可行?

4 个答案:

答案 0 :(得分:6)

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;
}

Andalso,您必须为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;
    }
};

答案 1 :(得分:2)

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

struct X
{
    std::string name;

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

你甚至可以把它变成朋友,让name私密等等。

Live example

答案 2 :(得分:2)

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>;

现在创建两个容器别名,您无需指定哈希。

添加新的hashable:

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

Foo适用于un_setun_map

我会将std容器和元组的支持添加到hashing命名空间中(覆盖它们的函数hash),并且神奇地这些也会起作用。

答案 3 :(得分:1)

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

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的公共基础。

Live demo here