2017-12-31 42 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&>()))> 
      ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~ 

これは私がSTDの特殊化を定義するヘッダファイルです:私はいくつかの理由のために、定期的に、正しい方法でタイルと呼ばれるこのクラスのはstd ::ハッシュテンプレートを専門とする場合でも、コンパイラは文句を続けます::ハッシュ(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

「ハッシュ」を「タイル」ではなく他のヘッダに入れるのはちょっと奇妙なようです。おそらくあなたにいくつかの注文問題を含めることができます。 –

答えて

0

私はtemplahttps移動した場合:クラスの定義の後(タイルクラスが定義されているヘッダファイルに//stackoverflow.com/help/how-to-answerte特化をもちろん、それ以降はどこでも)、コードがコンパイルされます。

通常、自分でもクラスを実装する場合、これは問題ではありません。私は、このクラスが共有ライブラリに実装されていることと関係があると思います。私はC + +の達人ではないので、私はこれを説明することはできません。しかし、私はここに誰かがまだそれを説明するのが大好きだ。

関連する問題