# How to Implement Custom Hash Functions in Abseil C++: A Complete Guide

> Learn to implement custom hash functions in Abseil C++ by defining AbslHashValue. Combine your type's fields efficiently for optimal performance. Get the complete guide here.

- Repository: [Abseil/abseil-cpp](https://github.com/abseil/abseil-cpp)
- Tags: how-to-guide
- Published: 2026-07-12

---

**To implement custom hash functions in Abseil, define a templated free function `AbslHashValue` that combines your type's fields using `H::combine()` and returns the updated hash state.**

The Abseil C++ library provides a high-performance hashing framework centered around `absl::Hash` and the `HashState` machinery. To make your custom types compatible with Abseil's hash containers like `absl::flat_hash_map`, you must implement the `AbslHashValue` customization point. This approach allows you to integrate user-defined types without modifying the library itself, ensuring optimal performance and compatibility across the Abseil ecosystem.

## The AbslHashValue Customization Point

The Abseil hashing framework uses **AbslHashValue** as its primary extension mechanism. This templated free function allows you to define how your type's fields contribute to the hash computation.

The algorithm follows three conceptual steps:

1. **Receive a hash state** — The framework passes an `H` object (typically `absl::HashState`) into your function.
2. **Combine each member** — Call `H::combine(std::move(state), member...)` for every field you want to include.
3. **Return the updated state** — The returned `H` is then used by `absl::Hash` to produce the final `size_t` value.

Because `AbslHashValue` is a template, it works with any hash-state implementation, including internal types like `absl::HashStateImpl`, ensuring forward compatibility with the library's internal and external hash utilities.

## Step-by-Step Implementation

### Basic Struct Example

For a simple struct with primitive fields, implement `AbslHashValue` as a free function in the same namespace as your type:

```cpp
#include "absl/hash/hash.h"

struct Point {
  int x;
  int y;
};

template <typename H>
H AbslHashValue(H h, const Point& p) {
  return H::combine(std::move(h), p.x, p.y);
}

```

This enables `Point` to work immediately with `absl::flat_hash_set<Point>` and `absl::flat_hash_map<Point, T>`.

### Complex Types with Containers

When hashing classes containing standard library containers, `AbslHashValue` handles the recursive combination automatically:

```cpp
#include <string>
#include <vector>
#include "absl/hash/hash.h"

class Person {
 public:
  std::string name;
  std::vector<int> favorite_numbers;
};

template <typename H>
H AbslHashValue(H h, const Person& p) {
  h = H::combine(std::move(h), p.name);
  for (int n : p.favorite_numbers) {
    h = H::combine(std::move(h), n);
  }
  return h;
}

```

The `H::combine` method automatically dispatches to existing hash implementations for `std::string` and `int`, handling the variable-length vector iteration manually.

### Bridging std::hash and absl::Hash

You can make your type compatible with both the C++ standard library and Abseil by forwarding `std::hash` to `absl::Hash`:

```cpp
namespace std {
template <>
struct hash<Point> {
  size_t operator()(const Point& p) const noexcept {
    return absl::Hash<Point>{}(p);
  }
};
}

```

This pattern allows seamless use in both `std::unordered_map` and `absl::flat_hash_map`.

## Internal Mechanics and Source Files

According to the abseil-cpp source code, the hashing infrastructure resides in specific locations:

- **[`absl/hash/hash.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/hash.h)**: Defines the public `absl::Hash` class template and declares the `AbslHashValue` customization point.
- **[`absl/hash/internal/hash.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/internal/hash.h)**: Contains the low-level `HashState` and `HashStateImpl` classes that implement the actual mixing logic.
- **[`absl/hash/internal/city.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/internal/city.h)**: Houses CityHash-derived mixing primitives used by the default hash state to distribute entropy.

When `absl::Hash<T>{}(value)` is invoked, the library calls your `AbslHashValue` implementation, which feeds data into the cryptographic-strength mixing algorithms defined in the internal headers. Your custom function integrates directly with these components without requiring access to private implementation details.

## Summary

- Implement **custom hash functions in Abseil** by defining a templated `AbslHashValue` function for your type.
- Use **`H::combine()`** to fold each field into the hash state, returning the final state object.
- Place `AbslHashValue` in the same namespace as your type to ensure Argument-Dependent Lookup (ADL) works correctly.
- Forward `std::hash` specializations to `absl::Hash` for dual compatibility with standard and Abseil containers.
- Reference implementation details in [`absl/hash/hash.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/hash.h) and [`absl/hash/internal/hash.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/internal/hash.h) for advanced customization.

## Frequently Asked Questions

### Why should I use AbslHashValue instead of specializing std::hash?

Using `AbslHashValue` provides better integration with Abseil's entire hashing ecosystem, including `absl::flat_hash_map` and `absl::node_hash_set`. It also allows you to maintain a single definition that works for both `absl::Hash` and `std::hash` by forwarding the latter to the former, ensuring consistent hashing behavior across all containers while respecting the library's mixing and strength guarantees.

### Can I use AbslHashValue with Abseil's flat_hash_map containers?

Yes. Once you define `AbslHashValue` for your type, it becomes immediately usable as a key in `absl::flat_hash_map`, `absl::flat_hash_set`, `absl::node_hash_map`, and `absl::node_hash_set`. The containers automatically detect and use your custom hash implementation through the `absl::Hash` mechanism.

### How does H::combine handle different field types?

The `H::combine` method uses overload resolution to recursively hash each argument. It works with primitive types, standard library containers, and user-defined types that have their own `AbslHashValue` implementations. The function efficiently mixes entropy from each field into the running hash state using CityHash-derived algorithms implemented in [`absl/hash/internal/city.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/internal/city.h).

### Where is the hash state implementation defined in the Abseil source code?

The hash state implementation is primarily defined in [`absl/hash/internal/hash.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/internal/hash.h), which contains the `HashState` and `HashStateImpl` classes. The public interface in [`absl/hash/hash.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/hash.h) delegates to these internal implementations, which handle the low-level mixing and entropy distribution using primitives from [`absl/hash/internal/city.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/internal/city.h).