W jaki sposób hashujecie własne typy?

0

Potrzebowaliście kiedyś jakiegoś mniej standardowego hasha?

Zazwyczaj w hash table'u potrzebuje przechowa dość proste typy więc w moim przypadku kończy się to wciskaniem prymitywów do obszerniejszego typu obsługiwanego przez std::hash, patrz kod niżej. Gdy mam więcej pól do hashowania to używam boost::hash_combine, a jak nie mam boosta w projekcie to po prostu kopiuje implementacje bo można ją sprowadzić do jednej linijki - seed ^= std::hash<T>(value) + 0x9e3779b9 + (seed<<6) + (seed>>2);.

struct Pos2D
{
  int x, y;
  bool operator==(const Pos2D &other) const { return x == other.x && y == other.y; }

};

struct Pos2DHash
{
  std::size_t operator()(const Pos2D &key) const
  {
    unsigned long long val = 0;
    val |= static_cast<uint32_t>(key.y); // wiem, ze int nie ma gwarancji 4 bajtow - juz sie nie czepiajcie to tylko przyklad
    val |= (static_cast<unsigned long long>(key.x) << 32) & 0xffffffff00000000;

    return std::hash<unsigned long long>()(val);
  }
};
4

Jest jeszcze Abseil, kolekcja libek od Googla, która zawiera również mini-framework do haszowania, co wygląda tak:

#include <iostream>
#include <utility>

#include "absl/hash/hash.h"

struct Test {
    int a, b, c;

    template <typename H>
    friend H AbslHashValue(H h, const Test& t) {
        return H::combine(std::move(h), t.a, t.b, t.c);
    }
};

int main() {
    Test t{1, 2, 3};
    std::size_t str_hash = absl::Hash<Test>{}(t);
    std::cout << str_hash << '\n';
}

Haszuje też kontenery czy krotki, ale boost::hash też to robi.

1 użytkowników online, w tym zalogowanych: 0, gości: 1