Class 自身为无序集
Class with an unordered set of itself
我把我的问题简化为这个。我可以创建一个 class 具有无序集的模板类型本身吗?具体来说,例如一个 Square 有一个指向一组无序邻居的指针。我在尝试将散列函数与 class 本身集成时遇到了困难。
这是我的代码:
#include <iostream>
#include <unordered_set>
#define SIZE 200
#define MASTER 0
class Square;
namespace std{
template<>
struct hash<Square> {
std::size_t operator () (Square const &v) const
{
return v.r;
}
};
}
class Square{
public:
int c1, c2;
int r;
std::unordered_set<Square> *neigh;
Square() {
neigh = new std::unordered_set<Square>();
}
~Square(){
delete neigh;
}
bool operator==(const Square& second) {
return this->r == second.r
&& this->c1 ==second.c1
&& this->c2 == second.c2;
}
};
int main(int argc, char *argv[]) {
Square sq;
Square tt;
sq.neigh->insert(tt);
}
我尝试使用 g++ 和 FLAGS = --std=c++17 -Wall -Wextra -Wno-unused-parameter -Wno-unused-variable -ggdb 进行编译。收到的错误很大,从以下内容开始:
test.cpp: In member function ‘std::size_t std::hash<Square>::operator()(const Square&) const’:
test.cpp:15:20: error: invalid use of incomplete type ‘const class Square’
15 | return v.x;
我不知道这种情况的正确做法是什么。请考虑这是我需要的简化代码版本,所以我真的需要一个邻居字段。
要解决您所问的问题,只需在 Square
定义之前声明 std::hash<Square>::operator()
,但不要实现它:
namespace std{
template<>
struct hash<Square> {
std::size_t operator() (Square const &) const;
};
}
然后在Square
定义之后,定义std::hash<Square>::operator()
:
namespace std {
std::size_t hash<Square>::operator() (Square const& v) const
{
// return calculation
}
}
您的 insert
也有问题。您复制 一个带有指针的对象,然后两次销毁同一个指针。要解决这个问题,请使用 std::unique_ptr<std::unordered_set<Square>>
这会有所帮助,因为如果您尝试复制它会出现编译错误。
class Square{
public:
std::unique_ptr<std::unordered_set<Square>> neigh;
Square() : neigh{std::make_unique<std::unordered_set<Square>>()} {}
// no destructor needed
bool operator==(const Square& second) const { // should be const
// ...
}
};
然后您必须 move
对象到位:
sq.neigh->insert(std::move(tt));
或emplace
他们:
sq.neigh->emplace(...constructor arguments...);
我把我的问题简化为这个。我可以创建一个 class 具有无序集的模板类型本身吗?具体来说,例如一个 Square 有一个指向一组无序邻居的指针。我在尝试将散列函数与 class 本身集成时遇到了困难。 这是我的代码:
#include <iostream>
#include <unordered_set>
#define SIZE 200
#define MASTER 0
class Square;
namespace std{
template<>
struct hash<Square> {
std::size_t operator () (Square const &v) const
{
return v.r;
}
};
}
class Square{
public:
int c1, c2;
int r;
std::unordered_set<Square> *neigh;
Square() {
neigh = new std::unordered_set<Square>();
}
~Square(){
delete neigh;
}
bool operator==(const Square& second) {
return this->r == second.r
&& this->c1 ==second.c1
&& this->c2 == second.c2;
}
};
int main(int argc, char *argv[]) {
Square sq;
Square tt;
sq.neigh->insert(tt);
}
我尝试使用 g++ 和 FLAGS = --std=c++17 -Wall -Wextra -Wno-unused-parameter -Wno-unused-variable -ggdb 进行编译。收到的错误很大,从以下内容开始:
test.cpp: In member function ‘std::size_t std::hash<Square>::operator()(const Square&) const’:
test.cpp:15:20: error: invalid use of incomplete type ‘const class Square’
15 | return v.x;
我不知道这种情况的正确做法是什么。请考虑这是我需要的简化代码版本,所以我真的需要一个邻居字段。
要解决您所问的问题,只需在 Square
定义之前声明 std::hash<Square>::operator()
,但不要实现它:
namespace std{
template<>
struct hash<Square> {
std::size_t operator() (Square const &) const;
};
}
然后在Square
定义之后,定义std::hash<Square>::operator()
:
namespace std {
std::size_t hash<Square>::operator() (Square const& v) const
{
// return calculation
}
}
您的 insert
也有问题。您复制 一个带有指针的对象,然后两次销毁同一个指针。要解决这个问题,请使用 std::unique_ptr<std::unordered_set<Square>>
这会有所帮助,因为如果您尝试复制它会出现编译错误。
class Square{
public:
std::unique_ptr<std::unordered_set<Square>> neigh;
Square() : neigh{std::make_unique<std::unordered_set<Square>>()} {}
// no destructor needed
bool operator==(const Square& second) const { // should be const
// ...
}
};
然后您必须 move
对象到位:
sq.neigh->insert(std::move(tt));
或emplace
他们:
sq.neigh->emplace(...constructor arguments...);