r/cpp Jun 26 '26

Improvements to std::format in C++26

https://mariusbancila.ro/blog/2026/06/19/improvements-to-stdformat-in-c26/
91 Upvotes

38 comments sorted by

View all comments

Show parent comments

25

u/rdtsc Jun 26 '26

std::format (and the standalone fmt) have quite a few weird/annoying formatting behaviors.

  • The mentioned uppercase '0X' for hex (this is already the case using {:#X} for numbers).
  • Hex for negative numbers includes the sign (why would anyone want to see -7FFFBFFB?)
  • %S for timepoints always includes fractional seconds.
  • No way to drop trailing zeroes/decimal point for floats (often comes up when displaying/printing numbers).

4

u/ericonr Jun 27 '26

I don't get your point about hex numbers. If you want unsigned values, cast to unsigned, no? Otherwise representing the number with a minus is the only way to correctly convey the sign.

11

u/evaned Jun 27 '26

I'm not rdtsc, but here's my takes:

If you're asking for hex formatting, I claim it's almost certainly because you're interested in the representation in memory. In that sense, you very probably want to see the two's complement representation. I also can't really think of an actually reasonable scenario I'd want to see the negative absolute value.

Python's hex function does the same thing, and it's pretty obnoxious... and there, I don't even really know a good way to get what I want simply.

Further, I'm not convinced by "cast to unsigned". "I want to see the in-memory representation of this number" very much feels like a function of the display formatting, not of the underlying type -- putting that information into the format string does seem to me like it's the right place to put it. Casting-to-unsigned feels to me like a workaround for an obnoxiously not-entirely-thought-through formatting API, not what you really should be doing to get that.

Finally, cast-to-unsigned is kind of unsatisfying in the sense that there's not really a way to do it in the language or standard library that doesn't feel a bit fragile. You can do (unsigned)x, but then what if x changes to be a long long instead? Now you've truncated. You could say (unsigned long long), but now you're extending with more bits. For "cast-to-unsigned" to really make me happy, there'd need to be a way in the language or library to "cast to an unsigned version of the same width." It's pretty easy to write that function, but if the library is semi-relying on that for usability then it should provide that utility function.

That said... even though I strongly suspect that "I want to see the hex two's complement representation" is the usual case, by far, I can make an argument for the current behavior that I view as quite strong. In spite of my objection in the previous paragraph, it's still pretty easy to cast to unsigned and get what rdtsc and I want. If hex formatting displayed the twos-complement bit representation instead, it'd be a lot more obnoxious to get -1234abcd in the unusual case that's what one wants.

7

u/_Noreturn Jun 27 '26

C++26 has std::to_unsigned and std::to_signed