# How to Use fmt::format for String Formatting in Modern C++

> Learn to use fmt::format for string formatting in C++. Master replacement fields, positional indices, named arguments, and format specifiers for powerful text manipulation.

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

---

**Use `fmt::format` from the fmtlib/fmt library by including `<fmt/core.h>` and calling the function with a format string containing curly-brace replacement fields, optionally using positional indices, named arguments via `fmt::arg()`, and format specifiers for width, precision, and alignment.**

The `fmt` library (fmtlib/fmt) provides a modern, type-safe alternative to C's `printf` and C++ iostreams. The core formatting functionality lives in [`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h) and [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h), offering compile-time checking and Pythonic syntax. Unlike traditional formatting methods, `fmt::format` validates format strings and argument types at compile time when possible, catching mismatched arguments or invalid specifiers before your program runs.

## Understanding the fmt::format Architecture

The `fmt` library organizes its functionality across three primary header files. In [`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h), you will find the **Core API** exposing `fmt::format`, `fmt::print`, and the `fmt::arg` helper for named parameters. The parsing machinery for format strings resides in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h), which contains the template metaprogramming that drives the replacement field logic. 

The heavy lifting occurs in either `src/format.cc` when building as a compiled library, or [`include/fmt/format-inl.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format-inl.h) when using the **header-only** mode via the `FMT_HEADER_ONLY` macro. This architecture enables `fmt::format` to parse format strings at compile time whenever possible, storing the result as static format-string objects that minimize runtime overhead.

## Basic fmt::format Syntax and Replacement Fields

At its foundation, `fmt::format` interleaves ordinary text with **replacement fields** delimited by `{` and `}`. The simplest usage inserts arguments in order using empty braces.

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

int main() {
    std::string s = fmt::format("The answer is {}.", 42);
    // s == "The answer is 42."
}

```

Each `{}` constitutes a replacement field that consumes the next argument in sequence. The syntax mirrors Python's `str.format`, as documented in [`doc/syntax.md`](https://github.com/fmtlib/fmt/blob/main/doc/syntax.md), and supports automatic left-to-right indexing for omitted argument identifiers.

## Positional and Named Arguments

### Explicit Positional Indices

You can reorder arguments using explicit positional indices inside the braces. This is particularly useful when translating strings where word order varies between languages.

```cpp
std::string s = fmt::format("{1}, {0}!", "world", "hello");
// s == "hello, world!"

```

Mixing automatic indexing (empty braces) with explicit indices triggers a compile-time error, ensuring consistency in argument handling.

### Named Arguments via fmt::arg

For complex formatting scenarios with many parameters, named arguments improve readability. Use the `fmt::arg` function defined in [`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h) to bind names to values.

```cpp
std::string s = fmt::format("{greeting}, {name}!",
                           fmt::arg("greeting", "hi"),
                           fmt::arg("name", "fmt"));
// s == "hi, fmt!"

```

## Format Specifiers for Width, Alignment, and Numeric Output

The optional `:format_spec` section inside replacement fields controls visual presentation. The grammar supports width, precision, alignment, fill characters, sign handling, alternate forms, and type conversion.

### Alignment and Fill Characters

Control text positioning using `<` (left), `>` (right), and `^` (center) alignment operators, optionally preceded by a fill character.

```cpp
fmt::print("[{:<10}]\n", "left");   // "[left      ]"
fmt::print("[{:>10}]\n", "right");  // "[     right]"
fmt::print("[{:^10}]\n", "center"); // "[  center  ]"
fmt::print("[{:*^10}]\n", "star");  // "[***star***]"

```

### Numeric Formatting Flags

Apply sign indicators, alternate forms, and zero-padding to numeric types using specific flags before the type specifier.

```cpp
fmt::print("{:+d} {:+d}\n", 7, -7);   // "+7 -7"
fmt::print("{:#06x}\n", 0xfe);       // "0x00fe"
fmt::print("{:08d}\n", 42);          // "00000042"

```

The `+` flag forces a sign on positive numbers, `#` triggers the alternate form (such as `0x` for hexadecimal), and `0` enables zero-padding up to the specified width.

### Precision for Floating-Point and Strings

Precision behaves contextually: for floating-point types it specifies digits after the decimal point, while for strings it truncates to the specified character count.

```cpp
fmt::print("{:.2f}\n", 3.14159);   // "3.14"
fmt::print("{:.4}\n", "hello world"); // "hell"

```

## Locale-Aware Formatting

The `L` flag enables locale-specific formatting, inserting appropriate digit grouping separators for the current global locale.

```cpp
auto loc = std::locale("en_US.UTF-8");
fmt::print("{:L}\n", 1234567890);   // "1,234,567,890"

```

This functionality is implemented in the formatting engine within [`include/fmt/format-inl.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format-inl.h) or `src/format.cc`, depending on your build configuration.

## Compile-Time Safety with fmt::format

When using C++20 or providing compile-time constant format strings, `fmt::format` validates replacement fields during compilation. Invalid specifiers or type mismatches generate compilation errors rather than runtime exceptions.

```cpp
// This fails to compile because 'd' is not valid for a string.
std::string s = fmt::format("{:d}", "text");

```

Even when format strings are determined at runtime, the library throws `fmt::format_error` for mismatched arguments, maintaining exception safety throughout the formatting pipeline implemented in [`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h).

## Summary

- **Include `<fmt/core.h>`** to access `fmt::format`, `fmt::print`, and `fmt::arg` in the fmtlib/fmt library.
- **Use replacement fields `{}`** for automatic argument indexing, or specify positions explicitly with `{0}`, `{1}`, etc.
- **Employ named arguments** via `fmt::arg("name", value)` for readability in complex formatting operations.
- **Control presentation** using format specifiers for width (`10`), alignment (`<`, `>`, `^`), fill characters (`*`), and numeric flags (`+`, `#`, `0`).
- **Leverage compile-time checking** to catch format string errors at build time when using constant format strings.
- **Reference implementation details** in [`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h), [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h), and `src/format.cc` for advanced customization.

## Frequently Asked Questions

### What header file do I need to include for fmt::format?

Include `<fmt/core.h>` for the basic formatting API including `fmt::format` and `fmt::print`. For advanced features or header-only usage, you may also need `<fmt/format.h>` or `<fmt/format-inl.h>` when defining `FMT_HEADER_ONLY` before your includes.

### Can I mix positional and named arguments in fmt::format?

No, mixing automatic indexing (empty `{}`), explicit positional indices (`{0}`, `{1}`), and named arguments in the same format string results in a compile-time error. The parser in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h) enforces consistent argument referencing throughout the format string.

### How does fmt::format handle compile-time format string checking?

When the format string is a compile-time constant (C++20 `consteval` contexts or `constexpr` strings), the parser runs during compilation, validating specifier compatibility with argument types. Invalid combinations like `{:d}` for strings cause compilation failures rather than runtime exceptions.

### What is the difference between fmt::format and fmt::print?

`fmt::format` returns a `std::string` containing the formatted result, while `fmt::print` writes directly to `stdout` or a specified file stream without creating an intermediate string object. Both functions share the same replacement field syntax and parsing logic defined in [`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h).