2017-05-14 10 views
2

저는 Conway의 "Game of Life"를 코딩하려고합니다. 내 목표에 가까워지고있는 동안 나는 컴파일러 오류와 붙어있어 :"C++ 라이브러리는이 유형의 해시를 제공하지 않습니다." - std :: unordered_map에서 자신의 클래스 사용하기

C2338: The C++ Library doesen't provide a hash for this type.

는 처음에 나는 SFML 클래스 sf::Vector2D을 사용했다. 나를 위해 작동하지 못했을 때 나는 실종 된 hashCode 메서드를 구현할 수 있기를 희망하면서 내 자신의 클래스를 작성했습니다.

내 질문 :
std::unordered_map에 대해 hashCode 방법을 사용하는 자체 클래스를 사용할 수 있습니까? 두 개의 숫자를 저장할 수있는 수업을 사용해야합니다. (나는 또한 std::tuple, struct 등을 시도했다.)

#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 
    } 
} 
+0

관련 없음 : 항상 시퀀스의 중간에 요소를 삽입하지 않으면'std :: list'는 거의 결코 좋은 컨테이너 선택이 아닙니다. –

답변

6

std::unordered_map (및 std::unordered_set)에 필요한 사용자 지정 해싱 함수가 저장된 타입의 멤버 함수가 아니다 :

여기에 내 코드의 한 시트이다. 당신은 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`. 
     } 
    }; 
} 

귀하의 경우는 정확하게 그것이 이런 식으로 일을 왜 이유이다 : 당신이 원하는 경우에 당신이 sf::Vector2D에 대한 std::hash를 전문으로 할 수 있습니다, 자신의 클래스를 구현 할 필요.

+1

관련 항목 : http://stackoverflow.com/a/38140932/214671; 이 특별한 경우, 나의 MAKE_HASHABLE 매크로는 전체 솔루션을'MAKE_HASHABLE (sf :: Vector2i, t.x, t.y)'로 줄인다. –