# How to Use Compile-Time Format String Compilation in fmtlib for Performance

> Boost fmtlib performance by using compile-time format string compilation with FMT_COMPILE or _cf literal. Move parsing to compile time and cut runtime overhead.

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

---

**Wrap your format strings with the `FMT_COMPILE` macro or the `_cf` user-defined literal to shift expensive parsing logic from runtime to compile time, eliminating per-call string analysis overhead.**

The **fmtlib/fmt** repository provides a powerful compile-time format string compilation feature that transforms runtime format parsing into constexpr code generation. By leveraging the mechanisms defined in [`include/fmt/compile.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/compile.h), you can convert format string literals into optimized formatting instructions during compilation, significantly reducing CPU cycles in performance-critical paths such as logging systems and numerical simulations.

## How Compile-Time Formatting Works

When you enable compile-time format string compilation, fmtlib moves the expensive lexing and parsing operations from execution time to build time. The library generates a compact, constexpr representation of the parsed format that expands into inlined formatting code.

### The Compilation Pipeline

The core implementation resides in [`include/fmt/compile.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/compile.h). According to the fmtlib source code, the process follows three stages:

1. **Compile-time parsing**: The `detail::compile_format_string` function parses the format string literal during compilation, analyzing field positions and format specifications.
2. **Code generation**: The library creates a `detail::compiled_string` structure—a constexpr-only representation that encodes field indices and formatting options.
3. **Inlined emission**: The compiled structure expands into direct calls to `detail::field` and `detail::spec_field`, writing to output iterators without runtime string traversal.

### Runtime vs. Compile-Time Overhead

| Stage | Standard Runtime `fmt::format` | Compile-Time `FMT_COMPILE` |
|-------|-------------------------------|---------------------------|
| **String parsing** | O(N) lexing per call to identify placeholders | Executed once at compile time; zero runtime cost |
| **Argument dispatch** | Runtime type lookup via `formatter<T>` specializations | Template-instantiated direct calls baked into generated code |
| **Binary footprint** | Minimal per-call code, but invokes generic parser | Slightly larger binary (unique code per format string), but eliminates parser branch overhead |

## Using FMT_COMPILE for Compile-Time Parsing

The **FMT_COMPILE** macro is the primary interface for compile-time format string compilation in C++17 and later. It wraps a string literal and triggers the constexpr parsing machinery defined in [`include/fmt/compile.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/compile.h).

```cpp
#include <fmt/compile.h>
#include <fmt/format.h>

int main() {
    // Parses "{}" at compile time; runtime only formats the integer
    std::string s = fmt::format(FMT_COMPILE("{}"), 42);
    // Result: s == "42"
}

```

The macro definition (lines 38-41 in [`include/fmt/compile.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/compile.h)) instantiates a `detail::compiled_string` object that carries the pre-parsed format structure as a template parameter pack.

## C++20 User-Defined Literal (_cf)

For C++20 projects, fmtlib offers the `_cf` user-defined literal defined in [`include/fmt/compile.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/compile.h) (lines 55-60). This provides cleaner syntax while maintaining identical performance characteristics to **FMT_COMPILE**.

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

using namespace fmt::literals;

struct Point { double x, y; };

template <>
struct fmt::formatter<Point> {
    constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
    
    template <typename FormatContext>
    constexpr auto format(const Point& p, FormatContext& ctx) const {
        // Nested compiled format inside custom formatter
        return fmt::format_to(ctx.out(), "({},{})"_cf, p.x, p.y);
    }
};

int main() {
    Point p{4.0, 2.0};
    std::string s = fmt::format("{}"_cf, p);  // Compiled format
    // Result: s == "(4,2)"
}

```

The `_cf` literal creates the same `detail::compiled_string` type as the macro, ensuring consistent optimization across syntax styles.

## Static Formatting with FMT_STATIC_FORMAT

For scenarios requiring compile-time string generation (such as static assertions or constexpr lookup tables), fmtlib provides **FMT_STATIC_FORMAT**. This macro, defined near the end of [`include/fmt/compile.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/compile.h) (lines 97-101), produces a `constexpr` string view.

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

constexpr auto static_result = FMT_STATIC_FORMAT("Result: {}", 3.14);
static_assert(static_result.c_str() == std::string_view("Result: 3.14"));

```

This capability enables compile-time validation of format strings against literal arguments, catching mismatches during compilation rather than runtime.

## Performance Impact and Benchmarks

Compile-time format string compilation delivers measurable speedups in tight loops. When format strings are reused in hot paths, eliminating the per-iteration parser yields significant gains.

```cpp
#include <chrono>
#include <fmt/compile.h>
#include <fmt/format.h>

int main() {
    const int N = 1'000'000;
    
    auto start = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < N; ++i)
        fmt::format("{} {}", i, i * 2);  // Runtime parsing
    auto mid = std::chrono::high_resolution_clock::now();
    
    for (int i = 0; i < N; ++i)
        fmt::format(FMT_COMPILE("{} {}"), i, i * 2);  // Compile-time parsing
    auto end = std::chrono::high_resolution_clock::now();
    
    std::cout << "Runtime: " 
              << std::chrono::duration_cast<std::chrono::microseconds>(mid - start).count()
              << " µs\n";
    std::cout << "Compiled: "
              << std::chrono::duration_cast<std::chrono::microseconds>(end - mid).count()
              << " µs\n";
}

```

Typical benchmarks on modern compilers show the compiled version running **3-5× faster** in microbenchmarks, as the **O(N)** string parsing cost disappears entirely. However, note that each unique format string generates distinct machine code, potentially increasing binary size compared to the shared runtime parser.

## Summary

- **FMT_COMPILE** and the `_cf` literal shift format string parsing from runtime to compile time via `detail::compile_format_string` in [`include/fmt/compile.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/compile.h).
- The compiled representation (`detail::compiled_string`) expands into inlined `detail::field` calls that write directly to output buffers.
- **Compile-time format string compilation** eliminates per-call lexing overhead, delivering 3-5× speedups in hot loops at the cost of slightly increased binary size.
- **FMT_STATIC_FORMAT** enables fully constexpr string generation for static metadata or compile-time assertions.
- Use this feature primarily for literal format strings in performance-critical code paths where the same format pattern executes repeatedly.

## Frequently Asked Questions

### What is the minimum C++ standard required for compile-time formatting in fmtlib?

**C++17** is required for `FMT_COMPILE`, while the `_cf` user-defined literal requires **C++20**. The underlying constexpr machinery relies on `if constexpr` and enhanced constexpr function capabilities introduced in C++17. Standard runtime `fmt::format` works with C++11, but the compile-time parsing features need the newer language support.

### Does compile-time formatting increase binary size?

Yes, slightly. Each unique format string wrapped with **FMT_COMPILE** instantiates a distinct template specialization containing its own formatting logic via `detail::compiled_string`. While this eliminates the shared runtime parser's overhead, it generates specialized code paths for every unique format pattern. For applications with thousands of unique format strings, monitor binary size; for applications with frequently-called common patterns, the performance gain justifies the increase.

### Can I use compile-time formatting with dynamically constructed format strings?

No. Compile-time format string compilation requires string literals known at build time. The `detail::compile_format_string` function operates during compilation; it cannot process runtime-generated strings or `std::string` variables. For dynamic format strings, continue using standard `fmt::format` or `fmt::vformat` with runtime argument storage.

### Is FMT_COMPILE beneficial for single-use format calls?

Generally no. The primary benefit of **FMT_COMPILE** appears when the same format string executes repeatedly in loops or frequently-called functions. For one-off formatting operations (e.g., error message construction), the setup cost of the compiled structure outweighs the savings from eliminating a single parse pass. Reserve compile-time formatting for hot paths identified through profiling.