Skip to content

Add ' format option for digit grouping - #4997

Draft
mpusz wants to merge 2 commits into
fmtlib:mainfrom
mpusz:iso-digit-grouping
Draft

mpusz wants to merge 2 commits into
fmtlib:mainfrom
mpusz:iso-digit-grouping

Conversation

@mpusz

@mpusz mpusz commented Oct 21, 2026

Copy link
Copy Markdown

This adds a grouping option to the standard format spec, placed after the
width and before the precision:

[[fill]align][sign][#][0][width][grouping][.precision][L][type]
grouping ::= "'" [" " | "," | "_" | "'"]

Digits are grouped in threes counting from the decimal marker. The character
after ' selects the separator:

Option Separator Groups With L
' U+202F NARROW NO-BREAK SPACE integer and fraction part decimal point only
' U+0020 SPACE integer and fraction part decimal point only
', '_ '' , _ ' integer part only error
fmt::format("{:'}", 1234567);             // "1 234 567" (U+202F)
fmt::format("{:'.6f}", 1234567.891234);   // "1 234 567.891 234" (U+202F)
fmt::format("{:',.6f}", 1234567.891234);  // "1,234,567.891234"
fmt::format("{:010',}", 1234567);         // "01,234,567"

' alone follows ISO 80000-1 and the SI Brochure. For char, U+202F is
emitted as UTF-8 when the literal encoding is UTF-8 and falls back to U+0020
otherwise. Wide character types get a single code unit. Each separator counts
as one column, so fill and alignment work as usual.

The option applies to integers (d or no type) and to floating-point values
(e, E, f, F, g, G or no type). The exponent is never grouped. With
0, the padding zeros are grouped too. Other combinations are format errors,
and checked format strings report them at compile time.

FMT_ISO_GROUPING_MIN2=1 enables the four-digit exception, which leaves a part of
exactly four digits unsplit.

This is the prototype for the WG21 paper P4410R0, "Locale-independent digit
grouping in std::format", and is opened as a draft to collect feedback.
Tests cover every separator, all character types, the error cases,
compile-time checks, locales and the four-digit exception.

🤖 Generated with Claude Code

mpusz and others added 2 commits October 20, 2026 13:26
Prototype of a ' option in the standard format spec, placed after width
and before precision:

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

Digits are grouped in threes counting from the decimal marker towards the
left and towards the right, as specified by ISO 80000-1 and the SI
Brochure. The separator is U+202F NARROW NO-BREAK SPACE (one code unit for
wide character types, UTF-8 for char when the literal encoding is UTF-8,
U+0020 otherwise) and counts as one column of width.

- Integers: presentation none or d.
- Floating point: none, e, E, f, F, g, G. In exponent form only the
  significand fraction is grouped.
- With 0, padding zeros are grouped too, never starting with a separator.
- With L, the locale supplies only the decimal point.
- Errors for other presentation types, bool, char, strings and pointers,
  diagnosed at compile time with checked format strings.
- FMT_ISO_GROUPING_MIN2=1 enables the four-digit exception, applied to
  the integer and fraction parts independently.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Extend the grammar to grouping ::= "'" [" " | "," | "_" | "'"]:

- '  : U+202F (U+0020 for char if the literal encoding is not UTF-8),
       groups the integer and fraction parts, may be combined with L
- ' (apostrophe and space): U+0020, otherwise the same as '
- ', '_ '' : the given character, groups only the integer part;
       combining them with L is an error

All forms share the presentation type restrictions, the grouping of
zero padding and the four-digit exception macro. The separator kind is
stored in a 3-bit field of basic_specs (fmt::group_separator).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant