Skip to content

Hashing Framework

Felix Gündling edited this page Oct 6, 2019 · 12 revisions

Introduction

Writing hashing functions for keys in hash-based containers is a tedious task. However, often hashing a struct involves hashing all its members and combining those hashes. Hashing iterable containers like std::vector<T> or std::set<T> involves hashing all entries and hash combining the computed hashes.

Cista contains a framework that automatically hashes any composition of scalars, iterable structs (like vector, set, etc.), and standard layout, non-polymorphic aggregate types. Char arrays are hashed as string. Additionally, it allows to implement a hash() const -> size_t member function or an overloaded std::hash<T>. Hashing is done recursively.

This hashing function is the default hash of cista::hash_map and cista::hash_set.

Example

Consider the following struct:

struct message {
  int code_{};
  std::string text_;
  std::string type_;
};

Depending on the application, a hashing function would probably often just hash all members. This is what cista::hashing<T> does. And it does it recursively - e.g the std::string members in the message struct are hashed as iterable of char entries.

message k{3, std::string{"4321"}, std::string{"1234"}};
CHECK(cista::hashing<message>{}(k) ==
      // hash message::type_ third
      cista::hash(std::string{"1234"},  // std::string is hashed as iterable!
                  // hash message::text_ second
                  cista::hash(std::string{"4321"},
                              // hash message::code_ first
                              cista::hash_combine(cista::BASE_HASH, 3))));

Strings

It is important to notice, that all string types yield the same hash if they contain the same sequence of characters. This includes:

  • Cista string cista::raw::string and cista::offset::string
  • Cista string view cista::raw::string_view and cista::offset::string_view
  • standard string std::string
  • standard string view std::string_view
  • char arrays: char[N]

This behaviour is very handy when it comes to lookups in cista::hash_map and cista::hash_set.