printf("Number %d, String %s", n, s);
but the types of n and s aren't int and char*, all hell breaks loose and you have the origin of a million CVEs. But how do you make that function signature typesafe, without the tools of modern templates? You sort of can't. One thing you can do is do string append stuff, but the syntax then is annoying: print("Number " + to_string(n) + ", String " + s);
This also creates a bunch of temporary strings, which is not ideal (and still relies on operator overloading, btw). In this world, using operators for this does make some sense: std::cout << "Number: " << n << ", String " << s;
Like, seen from this perspective, it's not the worst idea in the world, it does work nicely. The syntax really isn't too bad, IMHO (the statefulness part, though, really sucks). It also allows you to add formatting for your own types: just overload operator<<!Clearly, properly type-safe std::format is vastly superior, but the C++ of the 90s simply didn't have the template machinery to make that part of the standard library.
That is, for a custom type in Rust having rudimentary Debug output is one word added to the list of derive macros, the word "Debug". Almost everybody will write that, it's barely effort.
To get that in C++ I/O Streams you need to write an operator overload function and must be careful to write it correctly. Trivial types usually don't bother, but many C++ programmers are comfortable writing this for an important type.
For std::format you need to write a template which is already pretty scary, and then it needs to implement custom parse and format steps, this is because std::format allows your custom type to define its own custom formatting rules. This is extremely powerful, but everybody must pay for this power. I have not seen most people bother doing all this at all.
Both languages will have bidirectional compatibility with C++ so that code written in C++ can be directly accessed from Carbon and code written in Carbon can be directly accessed from C++. Neither of them use an FFI for compatibility.
Whereas while Kotlin used the Java ecosystem to bootstrap itself, it is clear that by now JetBrains rather wants to build their own Kotlin ecosystem, just like C++ and Objective-C took their own path after being plain translators into C.
std::cout << "Player is at" << _player_pos;
And get the x/y/z breakdown automatically. fmt::println("Player is at {}", _player_pos);It becomes cumbersome very fast.
So in effect Cpp2 pre-dates std::println. Herb will have been aware that it exists and is likely for C++ 23, but it doesn't make sense to ship software which requires features you suspect won't be widely available for several years. A "Hello, world" program should not be relying on bleeding edge features.