Skip to main content

Format spec syntax

Everything after the : in a replacement field is one small grammar. Learn it once and it applies to every type fmt knows how to format, including your own — a custom formatter<T> parses the same mini-language.

The grammar

[[fill]align][sign][#][0][width][.precision][L][type]

Every component is optional, and the ones present must appear in this order. An empty spec ({}) just means "default presentation for this type."

Component table

ComponentValuesMeaningPage
fill + alignany char + < > ^ =Pad character and alignment directionAlignment, fill and width
sign- + spaceWhich numbers get an explicit sign characterSign and numeric precision
#present or absentAlternate form: 0x/0b/0o prefixes, always-a-decimal-pointSign and numeric precision
0present or absentZero-pad to width, sign-awareSign and numeric precision
widthinteger or {}Minimum field widthAlignment, fill and width
.precisioninteger or {}Decimal places (floats) or max length (strings)Sign and numeric precision
Lpresent or absentApply the active locale's grouping/decimal separatorNumeric grouping and locales
typed x f s ? ...Presentation for this argument's typeType-specific presentation

Reading a spec

fmt::format("{:*^12}", "hi"); // "*****hi*****" — fill '*', center, width 12
fmt::format("{:+.3e}", 1234.5); // "+1.235e+03" — always sign, 3-digit precision, scientific
fmt::format("{:#010x}", 255); // "0x000000ff" — alternate form, zero-pad, width 10, hex

Reading {:*^12} component by component: fill is *, align is ^ (center), width is 12, no sign/precision/type given, so the type defaults to the argument's own default (string, unquoted). {:+.3e} has no fill/align, sign is + (always shown), precision 3, type e (scientific). {:#010x} has the alternate form flag, zero-padding, width 10, type x (lowercase hex) — the # and 0x prefix are what the # flag adds.

Dynamic width and precision

Width and precision can come from an argument instead of being written literally, using a nested {}. This is how you build a table with column widths computed at runtime.

int width = 12;
fmt::format("{:{}}", "hi", width); // width from the next argument
fmt::format("{:.{}}", 3.14159, 2); // precision from the next argument: "3.14"

Where the spec is parsed

The text after the : is handed to formatter<T>::parse for the argument's type — which is exactly why a custom type can accept its own spec letters instead of being limited to the built-in grammar. See formatter specialization for how parse consumes this text.

See also