#4997

Add `'` format option for digit grouping

Draftmpuszwants to merge intofrom

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:

OptionSeparatorGroupsWith L
'U+202F NARROW NO-BREAK SPACEinteger and fraction partdecimal point only
' U+0020 SPACEinteger and fraction partdecimal point only
', '_ '', _ 'integer part onlyerror
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

Activity

2

This pull request is a draft

Merging is unavailable until it is marked ready for review.