Hashing

Did you know that CAF can generate hash values for any inspectable type out of the box?

Consider this simple POD type with an inspect overload:

struct point_3d {
  int32_t x;
  int32_t y;
  int32_t z;
};

template<class Inspector>
bool inspect(Inspector& f, point_3d& point) {
  return f.object(point).fields(f.field("x", point.x),
                                f.field("y", point.y),
                                f.field("z", point.z));
}

The common algorithm of choice for generating hash values is the FNV algorithm, which is designed for hash tables and fast. Because this algorithm is so common, CAF ships an inspector that implements it: caf::hash::fnv (include caf/hash/fnv.hpp).

The FNV algorithm chooses a different prime number as the seed value based on whether you are generating a 32-bit hash value or a 64-bit hash value. In CAF, you choose the seed implicitly by instantiating the inspector with uint32_t, uint64_t, or size_t.

Because applying any value to the inspector always results in an integer value, caf::hash::fnv has a static member function called compute that takes any number of inspectable values. This means generating a hash boils down to a one-liner!

It also makes it very convenient to specialize std::hash. For our point_3d, the implementation boils down to this:

namespace std {

template <>
struct hash<point_3d> {
  size_t operator()(const point_3d& point) const noexcept {
    return caf::hash::fnv<size_t>::compute(point);
  }
};

} // namespace std

Under the hood, the inspector uses the inspect overload to traverse the object. Hash inspectors ignore type names, field names, etc. So passing a point_3d to the inspector results in the same result as passing x, y and z individually:

Source Code

using hasher = caf::hash::fnv<uint32_t>;
println("hash of (1, 2, 3): ", hasher::compute(1, 2, 3));
println("hash of point_3d(1, 2, 3): ", hasher::compute(point_3d{1, 2, 3}));

Output

hash of (1, 2, 3): 2034659765
hash of point_3d(1, 2, 3): 2034659765
Previous
Previous

Indenting Trace Logs