# How to Create a Custom fmtlib Formatter: Required Methods Explained

> Learn to create a custom fmtlib formatter by implementing parse and format methods. This guide explains the essential functions for your fmtlib formatter.

- Repository: [Hello World Foundation/fmt](https://github.com/fmtlib/fmt)
- Tags: how-to-guide
- Published: 2026-09-09

---

**To implement a custom fmtlib formatter, you must specialize `fmt::formatter<T>` and implement two member functions: `parse()` to handle format specifiers and `format()` to write the representation.**

The fmt library (fmtlib/fmt) provides a powerful extension mechanism for formatting user-defined types through template specialization. By implementing the `formatter` interface, you can integrate custom types directly into `fmt::format` strings with full support for width, alignment, and other format specifications.

## Required Methods for a Custom fmtlib Formatter

When specializing `fmt::formatter<T, Char>` (where `Char` defaults to `char`), you must provide exactly two methods that the library invokes during formatting operations.

### The `parse` Method

The `parse` method reads the format specifier that appears after the colon in a format string (e.g., `{:<10}`). It stores any parsed options and returns an iterator pointing to the first character after the specifier.

According to the source code in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h) (lines 2758–2772), the required signature is:

```cpp
constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin());

```

This method is called once per format string to extract width, precision, alignment, and custom flags.

### The `format` Method

The `format` method emits the actual string representation of your type into the output iterator provided by the formatting context. It receives the value to format and the context containing the output iterator.

The signature as implemented in the fmtlib source is:

```cpp
template <typename FormatContext>
auto format(const T& val, FormatContext& ctx) const -> decltype(ctx.out());

```

This template approach allows the method to work with different character types and output iterators.

## Minimal Implementation Skeleton

A minimal valid custom fmtlib formatter requires the following structure:

```cpp
template <> struct fmt::formatter<MyType> {
  constexpr auto parse(fmt::format_parse_context& ctx) -> decltype(ctx.begin()) {
    // Parse format specifications or skip to end
    return ctx.begin();
  }

  template <typename FormatContext>
  auto format(const MyType& val, FormatContext& ctx) const -> decltype(ctx.out()) {
    // Write formatted output
    return fmt::format_to(ctx.out(), "{}", val.to_string());
  }
};

```

Both methods must be defined even if your type does not support custom format specifiers.

## Inheriting from Existing Formatters

If your type should support standard format options (width, alignment, precision), inherit from an existing formatter rather than implementing `parse` manually. This approach leverages the base class's parsing logic while customizing only the output generation.

For example, inheriting from `fmt::formatter<int>` provides automatic handling of hex, octal, and padding specifiers.

## Complete Working Examples

### Basic Custom Formatter

The following example formats a `Point` struct as `(x,y)` without custom specifiers:

```cpp
#include <fmt/core.h>

struct Point { int x, y; };

template <> struct fmt::formatter<Point> {
  constexpr auto parse(fmt::format_parse_context& ctx) -> decltype(ctx.begin()) {
    return ctx.begin();  // No custom specifiers to parse
  }

  template <typename FormatContext>
  auto format(const Point& p, FormatContext& ctx) const -> decltype(ctx.out()) {
    return fmt::format_to(ctx.out(), "({},{})", p.x, p.y);
  }
};

int main() {
  Point pt{3, 4};
  fmt::print("Point = {}\n", pt);  // Output: Point = (3,4)
}

```

### Advanced Formatter with Standard Options

This example inherits from `fmt::formatter<int>` to support width and alignment while formatting a wrapper type:

```cpp
struct HexInt { int value; };

template <> struct fmt::formatter<HexInt> : fmt::formatter<int> {
  using fmt::formatter<int>::parse;  // Inherit standard parsing

  template <typename FormatContext>
  auto format(const HexInt& h, FormatContext& ctx) const -> decltype(ctx.out()) {
    return fmt::formatter<int>::format(h.value, ctx);
  }
};

int main() {
  HexInt h{255};
  fmt::print("{:>8x}\n", h);  // Output:       ff (right-aligned, hex)
}

```

## Summary

- **Two required methods**: Every custom fmtlib formatter must implement `parse()` and `format()` member functions.
- **Specialization point**: Create a template specialization of `fmt::formatter<T, Char>` for your type `T`.
- **Source location**: The primary template and requirements are defined in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h) at lines 2758–2772.
- **Inheritance option**: Derive from existing formatters like `fmt::formatter<int>` or `fmt::formatter<string_view>` to reuse standard format specifier parsing.
- **Const correctness**: The `format` method should be marked `const` as it does not modify the formatter state.

## Frequently Asked Questions

### What are the exact method signatures required for a custom fmtlib formatter?

Your specialization must provide `constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin())` and `template <typename FormatContext> auto format(const T& val, FormatContext& ctx) const -> decltype(ctx.out())`. These signatures are strictly enforced by the primary template in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h).

### Can I inherit from existing fmtlib formatters to avoid writing parsing logic?

Yes. If your type wraps a primitive or string-like type, inherit from the appropriate formatter (e.g., `fmt::formatter<int>`) and use `using` declarations to bring in the base `parse` method. This automatically enables width, alignment, and type-specific format specifiers without additional code.

### Where are the formatter requirements defined in the fmtlib source code?

The primary template definition requiring the `parse` and `format` methods is located in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h) at lines 2758–2772. The `test/format-test.cc` file contains additional reference implementations of built-in formatters that demonstrate best practices.

### Do I need to implement both parse and format methods even for simple types?

Yes. Both methods are mandatory because the formatting engine expects them at compile time. For types that do not support custom specifiers, implement `parse` to simply return `ctx.begin()` without consuming any characters. The `format` method must always be provided to define how your type converts to a string representation.