web-dev-qa-db-fra.com

Comment utiliser unordered_set?

J'essaie de définir un unordered_set comme ceci:

unordered_set<Point> m_Points;

Lorsque je le compile, j'obtiens l'erreur suivante:

La norme C++ ne fournit pas de hachage pour ce type.

Classe Point:

class Point{
    private:
        int x, y;
    public:
        Point(int a_x, int a_y)
            : x(a_x), y(a_y)
        {}
        ~Point(){}

        int getX()const { return x; }
        int getY()const { return y; }

        bool operator == (const Point& rhs) const{
            return x == rhs.x && y == rhs.y;
        }

        bool operator != (const Point& rhs) const{
            return !(*this == rhs);
        }
};
  • Comment/où puis-je définir une fonction de hachage pour Point?
  • Quelle serait une bonne fonction de hachage pour un point 2D?
23
brainydexter

std::unordered_set Vous oblige à écrire fonctions de hachage pour stocker et trouver vos propres types.

Les types de base et de nombreux types dans l'espace de noms std ont de telles fonctions de hachage dans std::hash<Key>. Ces fonctions suivent certaines règles :

  1. Accepte un seul paramètre de type Key.

  2. Renvoie une valeur de type size_t Qui représente la valeur de hachage du paramètre.

  3. Ne lève pas d'exceptions lorsqu'il est appelé.

  4. Pour deux paramètres k1 Et k2 Qui sont égaux, std::hash<Key>()(k1) == std::hash<Key>()(k2).

  5. Pour deux paramètres différents k1 Et k2 Qui ne sont pas égaux, la probabilité que std::hash<Key>()(k1) == std::hash<Key>()(k2) soit très petite, approchant 1.0/std::numeric_limits<size_t>::max().

Maintenant que nous avons supprimé les définitions, réfléchissons à ce qui serait une bonne fonction de hachage pour votre structure de points. Il y avait un demande que std::pair (Qui est très similaire à une structure de points) a une fonction de hachage, mais, malheureusement, cela n'a pas été intégré dans la norme C++ 11.

Mais nous avons de la chance: SO est génial et, bien sûr, vous pouvez déjà déjà trouvez la réponse . Notez que vous n'avez pas à hacher vous-même des entiers, car std::hash A déjà une spécialisation pour cela. Alors fouillons dans notre fonction de hachage, selon cette réponse :

namespace std
{
    template <>
    struct hash<Point>
    {
        size_t operator()(Point const & x) const noexcept
        {
            return (
                (51 + std::hash<int>()(x.getX())) * 51
                + std::hash<int>()(x.getY())
            );
        }
    };
}

Et nous avons terminé.

24
nijansen