On Fri, Oct 13, 2023 at 5:58 AM Hadriel Kaplan via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
Back in 2019, https://wg21.link/p1819r0 was submitted for "interpolated literals". I believe it was reviewed in EWG-Incubator back then, and again in 2022. There appears to have been consensus for the author to keep working on it generally, but no consensus on the proposal's specific details.

I'd like to propose a different solution - but only for the specific idea of having f-strings in C++, as opposed to a general string-interpolation framework.

I've written up a brief strawman here: https://tinyurl.com/3tr8rv22

The basic idea is to just syntactically replace an f-string with its std::format() counterpart, as a new step between phase 6 and 7 of translation, right after concatenation of string-literals. I.e., an f-string would just be syntactic-sugar for std::format().

More-detailed rules are written in the linked proposal above. It even includes a way to add a customization point should that be desired by the WG, at which point it's a form of interpolation and could perhaps fully replace P1819.

It's arguably a bit hacky, but it should be far simpler than P1819 to implement, use, and maybe even standardize.

I'm looking for feedback on whether this is an idea worth pursuing, or whether it's a horrible idea and I should never raise it again.

-hadriel

I think this approach is kind of a non-starter. We can't have f"x={x}" just mean std::format("x={}", x) for an important reason.

This means that std::print(f"x={x}") doesn't and can't work - which is the sort of thing that seems important to support - having to write std::print("{}", f"x={x}") is... less than ideal.

More generally, the issue is that there are a lot of uses of the format API that are not literally std::format(). In the standard we have std::print(), std::format_to(), etc. It would be really nice if those worked with f-strings as well. But even outside of the standard, we have all sorts of logging frameworks that would really want to be able to benefit from this feature in a nice way. For instance, let's say you use spdlog - which is one of the (if not the) most popular - you would really want to be able to write spdlog::info(f"x={x}") too, and have that work too. 

This is why I think the more viable approach is to have f-strings expand into something like an expression list. So f"x={x}" literally just evaluates as "x={}", x - so that wrapping it in a function call works. That is, std::format(f"x={x}") simply evaluates as std::format("x={}", x). Probably with the added requirement that it must be wrapped in a function call or something. That means that, yes, you have to write std::format(f"x={x}") if you just want the string, which is more verbose than what you're proposing. But that seems fine to me - I'm not sure the Rust community is complaining a lot about having to write format!("x={x}"), for instance. And it's still less verbose than what we write today and being more clear. Python gets away with f"..." just giving you a string because, well... it's Python so whatever, you just get a string.

Barry