# How to Compile Format Strings to Efficient Code with fmtlib

> Learn how to compile format strings to code with fmtlib using FMT_COMPILE for up to 2x faster formatting. Optimize your C++ code performance at build time.

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

---

**fmtlib eliminates run-time format string parsing by providing the `FMT_COMPILE` macro, which compiles format strings into optimized code at build time for up to 2× faster formatting performance.**

The fmtlib (also known as {fmt}) library offers a powerful compile-time formatting feature introduced in version 8.0.0 that transforms format strings into efficient code. By using the `FMT_COMPILE` macro, developers can compile format strings to code with fmtlib, bypassing dynamic parsing and achieving significant performance improvements in hot paths.

## How Compile-Time Formatting Works

The compile-time formatter implementation resides primarily in [`include/fmt/compile.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/compile.h) and operates through three distinct phases:

### Compile-Time Parsing

When you wrap a format string with `FMT_COMPILE("...")`, the macro passes the literal string to a `constexpr` parser implemented as `fmt::detail::compile_string`. This parser evaluates during compilation, analyzing the format string to build a **format specifier table** that describes types, width, precision, and other replacement field attributes.

Because this parsing happens at compile time, syntax errors in format strings are caught during the build phase rather than at run time.

### Formatter Type Generation

From the parsed specifier table, the library instantiates a template class `fmt::compile_string<>`. The `format` member function of this generated type contains the exact sequence of calls to `fmt::detail::write` that would normally be determined dynamically.

Since the compiler knows the complete format specification at build time, it can aggressively inline and optimize the formatting logic, often reducing the operation to simple direct-to-buffer writes.

### Zero Run-Time Parsing

When invoking `fmt::format(compiled, args...)`, the library bypasses the standard format-string parser in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h) and executes the pre-generated formatter directly. This yields identical output to standard `fmt::format` calls but with **no dynamic parsing overhead**, resulting in measurable speed-ups of up to approximately 2× for complex formatting strings.

## When to Use Compile-Time Formatting

Compile format strings to code with fmtlib in the following scenarios:

- **Performance-critical code paths** where the format string is a compile-time literal and remains constant. The elimination of run-time parsing provides measurable latency improvements.
- **Complex format specifications** with multiple arguments or intricate width/precision controls. Larger format specifications benefit disproportionately from compile-time optimization and inlining.
- **Hot loops** executing formatting operations frequently. The one-time compilation cost at build time pays dividends during execution.

Avoid compile-time formatting when handling strings assembled at run time, such as user input or concatenated fragments, as the `constexpr` parser requires literal strings.

## Practical Code Examples

### Basic Usage with FMT_COMPILE

Include [`fmt/compile.h`](https://github.com/fmtlib/fmt/blob/main/fmt/compile.h) and wrap your format string with the `FMT_COMPILE` macro:

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

int main() {
    int id = 42;
    const char* name = "Alice";

    // Compile-time formatting eliminates run-time parsing
    std::string s = fmt::format(FMT_COMPILE("User {} has ID {}"), name, id);
    // Result: "User Alice has ID 42"
}

```

### Combining with printf-Style Formatting

The compile-time parser also works with printf-style format strings via [`fmt/printf.h`](https://github.com/fmtlib/fmt/blob/main/fmt/printf.h):

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

int main() {
    double value = 3.14159;
    
    // Compile-time parsing for printf-style strings
    std::string s = fmt::sprintf(FMT_COMPILE("%0.2f meters"), value);
    // Result: "3.14 meters"
}

```

### Advanced: Direct Formatter Usage

For advanced scenarios, store the compiled formatter as a constexpr object and reuse it:

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

int main() {
    constexpr auto fmt_str = FMT_COMPILE("Result: {}");
    
    // fmt_str is a compile-time type that can be passed around
    std::string out = fmt::format(fmt_str, 7);
    // Result: "Result: 7"
}

```

### Performance Benchmark Comparison

The following example demonstrates the performance difference between compiled and dynamic formatting:

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

int main() {
    const int N = 1000000;
    auto start = std::chrono::high_resolution_clock::now();
    
    for (int i = 0; i < N; ++i) {
        // Compiled format string - parsed at build time
        fmt::format(FMT_COMPILE("value = {}"), i);
    }
    
    auto end = std::chrono::high_resolution_clock::now();
    std::cout << "Compiled format time: "
              << std::chrono::duration<double>(end - start).count()
              << " s\n";
}

```

Executing the same loop with `fmt::format("value = {}")` (without `FMT_COMPILE`) typically exhibits slower performance because each iteration repeats the format string parsing logic.

## Key Implementation Files

Understanding the source structure helps when debugging or extending compile-time formatting capabilities:

- **[`include/fmt/compile.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/compile.h)**: Implements the `constexpr` parser and defines the `FMT_COMPILE` macro and `compile_string` template class according to the fmtlib source code.
- **[`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h)**: Contains the core formatting machinery used by both compile-time and run-time formatters, including the `fmt::detail::write` functions referenced by generated formatters.
- **[`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h)**: Provides low-level output primitives and buffer management that the compiled formatter invokes directly.
- **[`include/fmt/printf.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/printf.h)**: Offers printf-style formatting compatibility and integrates with the compile-time parsing system.

## Summary

- **Use `FMT_COMPILE`** from [`include/fmt/compile.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/compile.h) to compile format strings to code with fmtlib and eliminate run-time parsing overhead.
- **Requires literal strings**: The format string must be known at compile time; dynamic strings fall back to standard `fmt::format` behavior.
- **Performance gains**: Compile-time formatting can deliver up to 2× speed improvements in complex formatting scenarios by enabling compiler optimizations and inlining.
- **Seamless integration**: The compiled formatter uses the same underlying `write` functions in [`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h) as the standard API, ensuring consistent output semantics.

## Frequently Asked Questions

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

Compile-time formatting requires C++14 or later to support the `constexpr` parsing logic implemented in `fmt::detail::compile_string`. While fmtlib supports C++11 for basic functionality, the `FMT_COMPILE` macro and associated compile-time optimizations leverage C++14 constexpr features introduced in version 8.0.0.

### Can I use FMT_COMPILE with dynamic format strings stored in variables?

No. The `FMT_COMPILE` macro relies on compile-time `constexpr` evaluation and requires string literals. If you pass a `std::string` or `const char*` variable, the compiler cannot instantiate the `compile_string` template because the value is unknown at build time. For dynamic strings, use the standard `fmt::format` function instead.

### Does compile-time formatting change the output format or behavior?

No. According to the fmtlib implementation in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h) and [`include/fmt/compile.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/compile.h), compiled formatters invoke the same `fmt::detail::write` functions as the run-time parser, producing identical output. The only difference is performance: compiled strings bypass the parsing phase and execute pre-generated formatting instructions directly.

### How much performance improvement can I expect from FMT_COMPILE?

Benchmarks indicate that compiling format strings to code with fmtlib delivers approximately 2× faster execution for complex format strings with multiple replacement fields, width specifiers, or precision controls. Simple strings with single arguments show smaller but measurable improvements, primarily due to eliminated parsing overhead and improved inlining opportunities for the compiler.