[英]“The C++ Library doesen't provide a hash for this type.” - Using own class in std::unordered_map
I am trying to code Conway's "Game of Life". 我正在尝试编码Conway的“生命游戏”。 While getting closer to my goal I got stuck with a compiler error: 在接近目标时,我陷入了编译器错误:
C2338: The C++ Library doesen't provide a hash for this type. C2338:C ++库没有为该类型提供哈希。
At first I used the SFML class sf::Vector2D
. 最初,我使用SFML类sf::Vector2D
。 When it failed to work for me I wrote a class of my own, hoping I could implement the missing hashCode
method. 当它对我不起作用时,我编写了自己的类,希望可以实现缺少的hashCode
方法。
My question is: 我的问题是:
Is it possible to uses my own class with its own hashCode
method for std::unordered_map
? 是否可以将我自己的类及其自身的hashCode
方法用于std::unordered_map
? I need to use a class, that can hold two numbers. 我需要使用一个可以容纳两个数字的类。 (I also tried std::tuple
, struct
and stuff). (我也尝试过std::tuple
, struct
和东西)。
Here is one sheet of my code: 这是我的代码之一:
#include "GameMechanics.h"
GameMechanics::GameMechanics(Elements * elements):elements(elements)
{
this->refreshTime = 1000000; //ms
this->clock.restart();
}
GameMechanics::~GameMechanics()
{
}
bool GameMechanics::isRunning()
{
return this->running;
}
void GameMechanics::setRunning(bool running)
{
this->running = running;
}
void GameMechanics::loop()
{
unsigned passedTime = clock.getElapsedTime().asMicroseconds(); //check passed time since the clock got restarted
this->timeHeap += passedTime; //add passed time to the timeheap
this->clock.restart();
//only refresh every "refreshTime" seconds
if (timeHeap >= this->refreshTime) {
std::cout << "Calculated new generation!" << std::endl;
this->timeHeap -= this->refreshTime;
this->calculateNextGeneration();
}
}
void GameMechanics::calculateNextGeneration()
{
std::list<sf::Vector2i> oldGeneration = this->elements->getElements(); // population in the moment
sf::Vector2u elements = this->elements->getElementCount();
std::unordered_map<MyVector2D, int> counter; //here is the problem. Thats the line that makes some trouble
for (std::list<sf::Vector2i>::iterator it = oldGeneration.begin(); it != oldGeneration.end(); it++) {
sf::Vector2i position = *it;
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
if (position.x + i >= 0 && position.x + i <= this->elements->getElementCount().x &&
position.y + j >= 0 && position.y + j <= this->elements->getElementCount().y)
{
if (counter.find(MyVector2D(position.x + i, position.y + j)) != counter.end())
{
counter.at(MyVector2D(position.x + i, position.y + j))++;
}
else //if there is no such element, create a new entry
{
counter.insert({ MyVector2D(position.x + i, position.y + j),1 });
}
}
}
}
}
//create new generation
this->brithNewGeneration(&counter);
}
void GameMechanics::brithNewGeneration(std::unordered_map<MyVector2D,int>* counter)
{
//this methode does work
std::list<sf::Vector2i> newGeneration;
// for (std::unordered_map<MyVector2D, int>::iterator it = counter->begin(); it != counter->end(); it++)
{
//if life vell with < 2 neighbours, it dies
//life cell with 2 or 3 neighbours will continue living
//life cell with >4 cells will die
//dead cell with 3 neighbours will start living
}
}
The custom hashing function required for std::unordered_map
(and std::unordered_set
) is not a member function of the stored type. std::unordered_map
(和std::unordered_set
)所需的自定义哈希函数不是存储类型的成员函数。 You need to specialize the std::hash template: 您需要专门化std :: hash模板:
namespace std {
template<>
struct hash<YourType> {
using argument_type = YourType;
using result_type = std::size_t;
result_type operator()(argument_type const &obj) const {
// Compute and return the hash value for `obj`.
}
};
}
Your case is precisely the reason why it's done this way: you can specialize std::hash
for sf::Vector2D
if you wish, no need to implement your own class. 您的案例正是这样做的原因:如果愿意,可以将std::hash
专用于sf::Vector2D
,而无需实现自己的类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.