如何将 unordered_set 与自定义结构一起使用?
我想将 unordered_set
与自定义 struct
一起使用.就我而言,自定义 struct
表示欧几里得平面中的 2D 点.我知道应该定义一个哈希函数和比较器运算符,我已经这样做了,您可以在下面的代码中看到:
结构点{诠释 X;整数 Y;点():X(0),Y(0){};Point(const int& x, const int& y) : X(x), Y(y) {};点(常量 IPoint& 其他){X = 其他.X;Y = 其他.Y;};点&运算符=(常量点和其他){X = 其他.X;Y = 其他.Y;返回*这个;};bool operator==(const Point& other) {if (X == other.X && Y == other.Y)返回真;返回假;};布尔运算符<(常量点&其他){if (X < other.X )返回真;else if (X == other.X && Y == other.Y)返回真;返回假;};size_t operator()(const Point& pointToHash) const {size_t 哈希 = pointToHash.X + 10 * pointToHash.Y;返回哈希;};};
但是,如果我按如下方式定义集合,则会出现以下错误:
unordered_set我的集;
<块引用>
错误 C2280 'std::hash<_Kty>::hash(const std::hash<_Kty> &)':试图引用已删除的函数
我错过了什么?
解决方案std::unordered_set 的第二个模板参数是用于散列的类型.并且在您的情况下默认为 std::hash<Point>
,它不存在.所以你可以使用 std::unordered_set<Point,Point>
如果哈希是相同的类型.
或者,如果您不想指定散列器,请为 Point
定义 std::hash
的特化,然后摆脱成员函数并实现散列在您的专业化的 operator()
的主体中,或从 std::hash 专业化调用成员函数.
#include <unordered_set>结构点{诠释 X;整数 Y;点():X(0),Y(0){};Point(const int& x, const int& y) : X(x), Y(y) {};点(常量点和其他){X = 其他.X;Y = 其他.Y;};点&运算符=(常量点和其他){X = 其他.X;Y = 其他.Y;返回*这个;};bool operator==(const Point& other) const {if (X == other.X && Y == other.Y)返回真;返回假;};布尔运算符<(常量点&其他){if (X < other.X )返回真;else if (X == other.X && Y == other.Y)返回真;返回假;};//这可以移入 std::hash<Point>::operator()size_t operator()(const Point& pointToHash) const noexcept {size_t 哈希 = pointToHash.X + 10 * pointToHash.Y;返回哈希;};};命名空间标准{模板<>结构哈希<点>{std::size_t operator()(const Point& p) const noexcept{返回 p(p);}};}主函数(){//如果 std::hash<Point> 不需要指定哈希存在std::unordered_set<Point>p;返回0;}
演示
I want to use an unordered_set
with a custom struct
. In my case, the custom struct
represents a 2D point in an euclidean plane. I know that one should define a hash function and comparator operator and I have done so as you can see in my code below:
struct Point {
int X;
int Y;
Point() : X(0), Y(0) {};
Point(const int& x, const int& y) : X(x), Y(y) {};
Point(const IPoint& other){
X = other.X;
Y = other.Y;
};
Point& operator=(const Point& other) {
X = other.X;
Y = other.Y;
return *this;
};
bool operator==(const Point& other) {
if (X == other.X && Y == other.Y)
return true;
return false;
};
bool operator<(const Point& other) {
if (X < other.X )
return true;
else if (X == other.X && Y == other.Y)
return true;
return false;
};
size_t operator()(const Point& pointToHash) const {
size_t hash = pointToHash.X + 10 * pointToHash.Y;
return hash;
};
};
However, I'm getting the error below, if I define the set as follows:
unordered_set<Point> mySet;
Error C2280 'std::hash<_Kty>::hash(const std::hash<_Kty> &)': attempting to reference a deleted function
What am I missing?
解决方案The second template parameter to std::unordered_set is the type to use for hashing. and will default to std::hash<Point>
in your case, which doesn't exist. So you can use std::unordered_set<Point,Point>
if the hasher is the same type.
Alternatively if you do not want to specify the hasher, define a specialization of std::hash
for Point
and either get rid of the member function and implement the hashing in the body of your specialization's operator()
, or call the member function from the std::hash specialization.
#include <unordered_set>
struct Point {
int X;
int Y;
Point() : X(0), Y(0) {};
Point(const int& x, const int& y) : X(x), Y(y) {};
Point(const Point& other){
X = other.X;
Y = other.Y;
};
Point& operator=(const Point& other) {
X = other.X;
Y = other.Y;
return *this;
};
bool operator==(const Point& other) const {
if (X == other.X && Y == other.Y)
return true;
return false;
};
bool operator<(const Point& other) {
if (X < other.X )
return true;
else if (X == other.X && Y == other.Y)
return true;
return false;
};
// this could be moved in to std::hash<Point>::operator()
size_t operator()(const Point& pointToHash) const noexcept {
size_t hash = pointToHash.X + 10 * pointToHash.Y;
return hash;
};
};
namespace std {
template<> struct hash<Point>
{
std::size_t operator()(const Point& p) const noexcept
{
return p(p);
}
};
}
int main()
{
// no need to specify the hasher if std::hash<Point> exists
std::unordered_set<Point> p;
return 0;
}
Demo
相关文章