2017-12-31 63 views
0

공유 라이브러리에 정의 된 클래스의 인스턴스를 unordered_map의 키로 사용하려고합니다.unordered_map에 사용자 정의 유형을 저장하기 위해 std :: hash를 특수화 할 수 없습니다.

/usr/include/c++/7/bits/hashtable_policy.h:87: error: no match for call to ‘(const std::hash<Tile>) (const Tile&)’ 
    noexcept(declval<const _Hash&>()(declval<const _Key&>()))> 
      ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~ 

이 내가 표준의 전문화를 정의하는 헤더 파일 : 나는 어떤 이유로, 일반, 올바른 방법으로 타일이라는 클래스의 표준 : 해시 템플릿을 전문으로하지만 컴파일러는 불평 유지 :: 해시 (pathfinder.h) :

#ifndef PATHFINDER_H 
#define PATHFINDER_H 

#include <vector> 
#include <unordered_set> 
#include <unordered_map> 
#include <memory> 

#include "Libworld/world.h" 
#include "node.h" 
#include "nodifier.h" 
#include "pathgenerator.h" 

namespace std { 
    template <> 
    struct hash <Tile> { 
     public: 
      size_t operator() (const Tile & theTile) const noexcept { 
       return ((32768 * theTile.getXPos ()) + theTile.getYPos ()); 
      } 
      size_t operator() (const Tile * theTile) const noexcept { 
       return ((32768 * theTile->getXPos ()) + theTile->getYPos ()); 
      } 
    }; 

    template <> 
    struct equal_to <Tile> { 
     bool operator () (const Tile & lhs, const Tile & rhs) const { 
      return (lhs == rhs); 
     } 
    }; 
} 

class Pathfinder { 
    private: 
     std::vector < std::unique_ptr <Tile> > theWorld; 
     QString theWorldName; 
     int worldRows, worldColumns, numberOfEnemies, numberOfHealthPacks; 

     std::unordered_set < std::shared_ptr <Node> > worldNodes; 
     std::unordered_map < Tile, bool > hasEnemyOrHealthPack; 

     std::shared_ptr <Nodifier> worldNodifier; 
     std::shared_ptr <PathGenerator> worldPathGenerator; 

     Tile startingTile, endingTile; 
     std::shared_ptr <Node> startingNode, endingNode; 

     // unsigned int findTileWithLocation (std::vector < std::unique_ptr <Node> > * nodesList, int x, int y) const; 

     void generateNodes (); 
     void generateHasEnemyOrHealthPack (World worldLoader, int numberOfEnemies, int numberOfHealthPacks); 

public: 
    Pathfinder (QString initialWorldName, 
       Tile initialStartingTile, 
       Tile initialEndingTile, 
       std::shared_ptr <Nodifier> initialWorldNodifier, 
       std::shared_ptr <PathGenerator> initialWorldPathGenerator, 
       int initialNumberOfEnemies, 
       int initialNumberOfHealthPacks); 

    QString getWorldName () const; 
    void loadNewWorld (const QString & newWorldName); 
    void loadNewWorld (const QString & newWorldName, const Tile & newWorldStartingTile, const Tile & newWorldEndingTile); 

    Tile getStartingTile () const; 
    void setStartingTile (const Tile & newStartingTile); 
    Tile getEndingTile () const; 
    void setEndingTile (const Tile & newEndingTile); 
    std::shared_ptr <Nodifier> getWorldNodifier () const; 
    void setWorldNodifier (const std::shared_ptr <Nodifier> & newWorldNodifier); 
    Tile getTileFromWorld (int x, int y); 

    void printNodes (); 
    void printWorld (); 

    std::list < std::pair <int, int> > generatePath (); 
}; 

#endif 

그리고이 타일의 정의를 포함하는 공유 라이브러리의 headerfile입니다 :

#ifndef WORLD_H 
#define WORLD_H 

#include "world_global.h" 
#include <vector> 
#include <memory> 
#include <QObject> 
#include <QImage> 

class Tile 
{ 
public: 
    Tile(int xPosition, int yPosition, float tileWeight); 
    virtual ~Tile() =default; 
    float getValue() const {return value;}; 
    void setValue(float newValue) {value = newValue;}; 
    int getXPos() const {return xPos;}; 
    int getYPos() const {return yPos;}; 
    void setXPos(int newPos) {xPos = newPos;}; 
    void setYPos(int newPos) {yPos = newPos;} 
    bool operator== (const Tile & other) const 
     {return (getXPos() == other.getXPos()) && (getYPos() == other.getYPos());}; 

protected: 
    int xPos; 
    int yPos; 
    float value; 
}; 

class Enemy : public Tile 
{ 
public: 
    Enemy(int xPosition, int yPosition, float strength); 
    virtual ~Enemy() = default; 
    bool getDefeated() const {return defeated;} 
    void setDefeated(bool value) {defeated = value;}; 

private: 
    bool defeated; //false by construction 
}; 

class PEnemy: public QObject, public Enemy 
{ 
    Q_OBJECT 
public: 
    PEnemy(int xPosition, int yPosition, float strength); 
    virtual ~PEnemy() = default; 
    float getPoisonLevel() const; 
    void setPoisonLevel(float value); 

public slots: 
    bool poison(); 

signals: 
    void dead(); 
    void poisonLevelUpdated(int value); 

private: 
    float poisonLevel; 
}; 

class Protagonist: public QObject, public Tile 
{ 
    Q_OBJECT 
public: 
    Protagonist(); 
    void setXPos(int newPos) {xPos = newPos; emit posChanged(xPos, yPos);} 
    void setYPos(int newPos) {yPos = newPos; emit posChanged(xPos, yPos);} 
    void setPos(int newX, int newY) {if (xPos != newX || yPos != newY) {xPos = newX; yPos = newY; emit posChanged(xPos, yPos);}} 
    float getHealth() const {return health;}; 
    void setHealth(float value) {health = value;} 

    float getEnergy() const {return energy;} 
    void setEnergy(float value) {energy = value;} 

signals: 
    void posChanged(int x, int y); 

private: 
    float health; //100.0f by construction 
    float energy; //100.0f by construction 
}; 

class WORLDSHARED_EXPORT World 
{ 
public: 
    World() = default; 
    //to obtain non-overlapping enemies and healthpacks you should call the following 3 methods in this order 
    std::vector<std::unique_ptr<Tile>> createWorld(QString filename); 
    std::vector<std::unique_ptr<Enemy>> getEnemies(unsigned int nrOfEnemies); 
    std::vector<std::unique_ptr<Tile>> getHealthPacks(unsigned int nrOfPacks); 
    std::unique_ptr<Protagonist> getProtagonist(); 
    int getRows() const {return rows;}; 
    int getCols() const {return cols;}; 

private: 
    int rows, cols; 
    QImage world; 
    std::vector<QPoint> used; //only for internal use 
}; 


#endif // WORLD_H 

내가 모든 것을 제대로하고 있어요 확신 , 그래서 누군가가 왜 이것이 컴파일되지 않는지를 말할 수 있다면 나는 좋아할 것이다.

대단히 감사드립니다. 나는 오랫동안 이것을 고집했습니다.

안부, 여호수아

+0

관련이 없지만 기본 템플릿과 동일한 작업을 수행하는 'equal_to'전문은 중복됩니다. – StoryTeller

+0

그리고 둘째, 정보의 비율을 귀하의 게시물에 줄이십시오. 코드 샘플에는 많은 관련이없는 것들이 포함되어 있습니다. 그것을 [mcve]로 바꾸십시오. 제발. – StoryTeller

+0

'Tile'이 아닌 다른 헤더에'hash '을 쓰는 것이 이상하게 보입니다. 주문 문제를 포함시킬 수 있습니다. –

답변

0

나는 templahttps 이동하는 경우 : 클래스의 정의 뒤에 (타일 클래스가 정의 된 헤더 파일에 //stackoverflow.com/help/how-to-answerte 전문화를 물론, 그 뒤에는 아무 데나) 코드가 컴파일됩니다.

일반적으로 클래스도 직접 구현할 때 중요하지 않습니다. 나는이 클래스가 공유 라이브러리에서 구현된다는 것과 관련이 있다고 생각한다. 나는 C++ 전문가가 아니기 때문에 이것을 설명 할 수 없다. 그러나 나는 여기 누군가가 여전히 그것을 설명하는 것을 좋아할 것입니다.