(2) is a point I firmly agree with (though not everyone does), but it’s a hard one.
Here’s the way I think about it. I don’t think I’m wrong but I’m absolutely open to being told otherwise.
C++ is a language. It has a standard library. The library depends on the language, but the language shouldn’t depend on the library. This is because many applications cannot use the standard library, or parts of it.
The conceptual issue with fstrings in C++ is that the formatting is done on a library level. An fstring would be a language feature. It wouldn’t be reasonable for syntax sugar to resolve to a library call.
So what we’d need is a way of having parameterised strings that the language knows to separate out into parameters in a function call. For instance:
f(f”Hello, {planet}”);
would resolve to:
f(“Hello, {}”, planet);
such that replacing f with std::format, std::print (C++23), fmt::format, fmt::print, spdlog::info, spdlog::error, or even scn::scan (?), would do exactly what you want.
However, the expression f”Hello, {planet}” would be meaningless on its own, and care would need to be taken to avoid:
std::string x = f”Hello, {planet}”;
from resolving to:
std::string x = “Hello, {}”, planet;
Which would be equivalent to
std::string x = planet;
Thanks to C++‘s ludicrous comma operator.