# How to Use Abseil Hash Framework with Custom Types in C++

> Learn to make custom C++ types hashable using the Abseil hash framework. Implement AbslHashValue and H::combine for seamless integration with absl::Hash and containers.

- Repository: [Abseil/abseil-cpp](https://github.com/abseil/abseil-cpp)
- Tags: tutorial
- Published: 2026-07-16

---

**To make a custom type hashable with Abseil, implement a template `AbslHashValue` friend function that combines your data members using `H::combine`, enabling use with `absl::Hash<T>` and Abseil containers like `absl::flat_hash_map`.**

The Abseil library provides a robust hashing framework that extends beyond standard `std::hash` to deliver high-quality, consistent hashing across its container implementations. Located in the abseil/abseil-cpp repository, the core API resides in [`absl/hash/hash.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/hash.h), while the underlying algorithms and hardware-accelerated optimizations are implemented in [`absl/hash/internal/hash.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/internal/hash.h). This framework allows you to integrate user-defined types seamlessly using the `AbslHashValue` extension point.

## Understanding the Hashable Contract

A type becomes compatible with Abseil's hashing infrastructure when it satisfies one of two conditions. According to the implementation in [`absl/hash/hash.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/hash.h), the framework checks for `AbslHashValue` first, then falls back to `std::hash<T>`.

### AbslHashValue as the Primary Extension Point

The preferred method for making custom types hashable is implementing a template friend function named `AbslHashValue`. As defined in the source, this function must adhere to the following signature:

```cpp
template <typename H>
friend H AbslHashValue(H h, const MyType& v);

```

The function receives a hash state `h` (conforming to the internal `hash_internal::Hasher` concept) and returns the updated state after mixing the members of `v`. This design allows the framework to support piece-wise hashing and algorithmic optimizations without exposing internal details.

### Fallback to std::hash

If `AbslHashValue` is not defined, the framework automatically falls back to `std::hash<T>`. However, this bypasses Abseil's optimized algorithms and consistency guarantees.

## Implementing AbslHashValue for Custom Types

To implement hashing for a custom struct, you define `AbslHashValue` as a friend function that delegates member hashing to `H::combine`. This method, utilized throughout the Abseil codebase including in [`absl/hash/hash_testing.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/hash_testing.h), ensures that each member contributes to the final hash value.

Consider a `Person` struct containing a string, integer, and vector:

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

struct Person {
  std::string name;
  int age;
  std::vector<double> scores;

  // Define the hash extension point
  template <typename H>
  friend H AbslHashValue(H h, const Person& p) {
    // Combine each member into the hash state
    return H::combine(std::move(h), p.name, p.age, p.scores);
  }
};

```

Once defined, you can use `Person` directly with `absl::Hash` or in Abseil containers:

```cpp
#include "absl/container/flat_hash_map.h"

int main() {
  absl::flat_hash_map<Person, int> map;
  Person alice{"Alice", 30, {95.0, 88.5}};
  
  map[alice] = 1;  // Works because Person satisfies the hashable contract
  size_t h = absl::Hash<Person>{}(alice);  // Direct hash calculation
}

```

The `H::combine` function handles the underlying algorithm details, including support for recursive hashing of composite types like `std::vector` and `std::string`.

## Why Prefer AbslHashValue Over std::hash?

Specializing `std::hash` works for standard containers, but Abseil's framework offers distinct advantages as implemented in [`absl/hash/internal/hash.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/internal/hash.h) and [`absl/hash/internal/city.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/internal/city.h):

**Consistency**: All Abseil containers (`absl::flat_hash_map`, `absl::node_hash_set`, etc.) use `absl::Hash` internally, ensuring identical hash values across your codebase regardless of container choice.

**Performance**: The framework automatically utilizes hardware-accelerated CRC32 when available and employs piece-wise hashing algorithms (derived from CityHash) for large buffers. This optimization happens transparently in [`absl/hash/internal/hash.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/internal/hash.h) without requiring changes to your `AbslHashValue` implementation.

**Extensibility**: When your type contains other hashable types, `H::combine` recursively invokes their respective `AbslHashValue` implementations, creating a uniform hashing strategy without manual algorithm mixing.

## Advanced: Custom Hash Algorithms

For scenarios requiring a specific mixing strategy, you can create a custom hasher and integrate it within `AbslHashValue`. The only requirement is satisfying the internal `hash_internal::Hasher` concept used by the framework.

```cpp
struct MyHasher {
  template <typename T>
  static size_t Mix(const T& value, size_t state) {
    // Example: simple xor-shift mix
    return state ^ std::hash<T>{}(value) + 0x9e3779b97f4a7c15ULL;
  }
};

struct MyType {
  int field;
  
  template <typename H>
  friend H AbslHashValue(H h, const MyType& v) {
    // Use the custom mixing function
    return H::combine(std::move(h), MyHasher::Mix(v.field, /*state=*/0));
  }
};

```

This approach maintains compatibility with `absl::Hash` while allowing fine-grained control over the hash computation.

## Summary

- **Primary extension point**: Implement `template <typename H> friend H AbslHashValue(H h, const T& v);` to make custom types hashable.
- **Member mixing**: Use `H::combine` inside `AbslHashValue` to recursively hash data members, handling vectors, strings, and nested types automatically.
- **Implementation location**: The public API lives in [`absl/hash/hash.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/hash.h), while core algorithms and hardware optimizations reside in [`absl/hash/internal/hash.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/internal/hash.h) and [`absl/hash/internal/city.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/internal/city.h).
- **Container compatibility**: Once implemented, types work immediately with `absl::flat_hash_map`, `absl::Hash<T>`, and other Abseil containers.
- **Performance benefits**: The framework automatically applies hardware-accelerated CRC32 and CityHash-based algorithms without additional code.

## Frequently Asked Questions

### What is the exact signature required for AbslHashValue?

The function must be a template friend function accepting a hash state and your type, returning the updated state: `template <typename H> friend H AbslHashValue(H h, const MyType& v);`. This signature is required by the `absl::Hash` functor defined in [`absl/hash/hash.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/hash.h) to properly invoke piece-wise hashing.

### How does Abseil's framework handle hashing of composite types (members that are themselves custom types)?

When you call `H::combine(h, member)` inside `AbslHashValue`, the framework recursively checks for `AbslHashValue` on that member's type. If defined, it uses that implementation; otherwise, it falls back to `std::hash`. This recursive resolution happens transparently in [`absl/hash/internal/hash.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/internal/hash.h), allowing complex nested structures to hash correctly without manual delegation.

### Can I use std::hash specialization alongside Abseil's framework?

Yes, but Abseil prefers `AbslHashValue`. If both are defined, `AbslHashValue` takes precedence because `absl::Hash` checks for it first before falling back to `std::hash`. For consistency across Abseil containers, you should implement `AbslHashValue` even if `std::hash` is specialized.

### Where is the underlying hash algorithm implemented in the Abseil source?

The default algorithms are implemented in [`absl/hash/internal/hash.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/internal/hash.h) (core combiner logic and hardware CRC32 support) and [`absl/hash/internal/city.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/internal/city.h) (CityHash-based fallbacks). The public entry point in [`absl/hash/hash.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/hash/hash.h) dispatches to these internal implementations based on platform capabilities and type characteristics.