Live data from Hacker News

F-strings for C++26 proposal [pdf]

open-std.org

11–20 of 216 posts

Re: F-strings for C++26 proposal [pdf]

#11
So the f-string literal produces a basic_formatted_string, which is basically a reified argument list for std::format, instead of a basic_string. This allows eg. println to be overloaded to operate on basic_formatted_string without allocating an intermediate string

  std::println("Center is: {}", getCenter());
  std::println(f"Center is: {getCenter()}");  // same thing, no basic_string allocated
In exchange we have the following problems

  // f-strings have unexpected type when using auto or type deduction.
  // basic_string is expected here, but we get basic_formatted_string.
  // This is especially bad because basic_formatted_string can contain
  // dangling references.
  auto s = f"Center is: {getCenter()}";

  // f-strings won't work in places where providing a string currently
  // works by using implicit conversion. For example, filesystem methods
  // take paths. Providing a string is okay, since it will be implicitly
  // converted to a path, but an f-string would require two implicit
  // conversions, first to a string, then to path.
  std::filesystem::exists(f"file{n}.dat");  // error, no matching overload
There are two other proposals to fix these problems.

Re: F-strings for C++26 proposal [pdf]

#12
This links to a “decays_to” proposal:

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p33...

And observes that this additional feature is needed to avoid dangling references. And, as a long time C++ programmer, this illustrates one of the things I dislike most about C++. In most languages, if you make a little mistake involving mixing up something that references something else with something that contains a copy, you end up with potential overhead or maybe accidental mutation. In Rust, you get a compiler error. In C++, you get use-after-free, and the code often even seems to work!

So now we expect people to type:

    auto s = f"{foo}";
And those people expect s to act like a string. But the designers (reasonably!) do not want f to unconditionally produce an actual std::string for efficiency reasons, so there’s a proposal to allow f to produce a reference-like type (that’s a class value, not actually a reference), but for s to actually be std::string.

But, of course, more advanced users might know what they’re doing and want to bypass this hack, so:

    explicit auto s = f"{foo}";
Does what they programmer actually typed: s captures foo by reference.

What could possibly go wrong?

(Rust IMO gets this exactly right: shared xor mutable means plus disallowing code that would be undefined behavior means that the cases like this where the code might do the wrong thing don’t compile. Critically, none of this actually strictly requires Rust’s approach to memory management, although a GC’d version might end up with (deterministic) runtime errors instead unless some extra work is done to have stronger static checking. And I think other languages should learn from this.)

Re: F-strings for C++26 proposal [pdf]

#13
post #9
post #4

Earlier quoted context omitted.

This is the sort of change that adds complexity to the language but reduces complexity in the code written in the language. We take those

how would this work with internationalized strings? especially if you have to change the order of things? You'd still need a string version with object ordering I would think

I'm skeptical that people would want to do this in a single expression.

Re: F-strings for C++26 proposal [pdf]

#14
post #3

Tangent: this sort of thing can be implemented without any change to libc++ (the runtime). Updates to compiler versions are sometimes postponed by users with big codebases that treat a libc++ change as something major. Why don't we see gcc or clang or msvc back porting stuff like this to an older version with a sort of future tag. It's normal to see __future__ in the python ecosystem, for instance.

If a codebase is fragile enough that libc++ changes have to be assumed breaking until proven otherwise, why take the risk? Presumably the application already has a "standard" way of formatting strings. If it ain't broke yada yada

It's not about assumed breaking, it's that when you upgrade libc++ you can become incompatible at runtime with your distro or any other number of libraries outside your control in ways that are difficult to detect

Re: F-strings for C++26 proposal [pdf]

#15
post #9
post #4

Earlier quoted context omitted.

This is the sort of change that adds complexity to the language but reduces complexity in the code written in the language. We take those

how would this work with internationalized strings? especially if you have to change the order of things? You'd still need a string version with object ordering I would think

f-strings are not an internationalization library.

Re: F-strings for C++26 proposal [pdf]

#16

So the f-string literal produces a basic_formatted_string, which is basically a reified argument list for std::format, instead of a basic_string. This allows eg. println to be overloaded to operate on basic_formatted_string without allocating an intermediate string std::println("Center is: {}", getCenter()); std::println(f"Center is: {getCenter()}"); // same thing, no basic_string allocated In exchange we have the fo…

Yes. The basic idea is that there's a specifier that allows a formatted string to transparently decay into an ordinary string (à la array-to-pointer decay) so that "auto" doesn't produce dangling references, and so that chains of more than one implicit conversion can take place.

Re: F-strings for C++26 proposal [pdf]

#17
post #12

This links to a “decays_to” proposal: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p33... And observes that this additional feature is needed to avoid dangling references. And, as a long time C++ programmer, this illustrates one of the things I dislike most about C++. In most languages, if you make a little mistake involving mixing up something that references something else with something that contains a…

IOW I believe it's the same thing as Rust's format_args! macro, but trying to get away without needing a separate format! macro by using implicit conversions.

Re: F-strings for C++26 proposal [pdf]

#18
post #10

Earlier quoted context omitted.

So it's less complex bringing in a 3rd party library and having to pass arguments? fmt library can also do something similar, but still requires the complexity of adding the library and passing arguments.

especially bringing in boost which isn't allowed in some codebases

boot is not allowed caused by the complexity. So some people disallow boost, here is the solution, just add the complexity directly to the language definition!

Re: F-strings for C++26 proposal [pdf]

#20
post #12

This links to a “decays_to” proposal: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p33... And observes that this additional feature is needed to avoid dangling references. And, as a long time C++ programmer, this illustrates one of the things I dislike most about C++. In most languages, if you make a little mistake involving mixing up something that references something else with something that contains a…

> But, of course, more advanced users might know what they’re doing and want to bypass this hack, so:

    explicit auto s = f"{foo}";
> Does what they programmer actually typed, so s captures foo by reference.

Wouldn't this problem be best solved by... not declaring s to have a guess-what-I-mean type? If you want to be explicit about the type of s, why not just say what that type is? Wouldn't that be even more explicit than "explicit auto"?

Post reply on HN