我知道通过定义一个单独的哈希函数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 ++中是否可行?
答案 0 :(得分:6)
std::unordered_set
在std
命名空间中定义。它使用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
私密等等。
答案 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_set
和un_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的公共基础。