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.