Annotations for C++26 Hashing -- Krystian Piękoś
Static reflection already makes generic hashing in C++26 far more expressive, but annotations push it into genuinely ergonomic territory. By letting types explicitly opt-in to hashing and allowing individual members or base classes to be cleanly excluded, we get a solution that is both powerful and readable.
Annotations for C++26 Hashing
by Krystian Piękoś
From the article:
In my recent post, I demonstrated how to use static reflection from C++26 to implement generic hash computation for custom types. Let's review the final implementation. The core of the solution is the calculate_hash() function, which iterates over sub-objects (including both base classes sub-objects and class/struct non-static data members) to compute a combined hash.
template <typename T>
concept Hashable = requires {
{ std::hash<T>{}(std::declval<T>()) } -> std::convertible_to<size_t>;
};template <typename T>
requires std::is_class_v<T>
size_t calculate_hash(const T& obj, size_t seed = 0)
{
constexpr auto ctx = std::meta::access_context::unchecked();
static constexpr auto r_subobjects = std::define_static_array(std::meta::subobjects_of(^^T, ctx));template for (constexpr auto r_sub : r_subobjects)
{
using Subobject_t = typename[:std::meta::type_of(r_sub):];
static_assert(Hashable<Subobject_t>, "Subobject must be hashable");
Utility::hash_combine(seed, obj.[:r_sub:])
}return seed;
}

Mixing your units can be disastrous. Wu Yongwei takes a quick look at C++ unit libraries that can help keep everything in order.
In today's post, I will explain one of C++'s biggest pitfalls: