Hello, and welcome to C++ Weekly. I'm your host, Jason Turner, available for code reviews
and on-site training. In this episode I want to talk about the differences between the format
that you're going to get with your C++20 compiler and the lib {fmt} that std is based on.
So as always, before moving on I want to point out that you should check out the notes in the
video description below, and be aware that you can suggest and vote on episode ideas
and be sure to check out my books and consider hiring me to do training on site at your company.
So first and foremost, I want to point out that I have GCC trunk mode with C++20 enabled,
and I have included the format header from lib {fmt} standalone library. Why
have I started here? Well, if I want to include from my standard library,
I can't yet - at the moment only Visual Studio's standard library actually has the library
available to it. So let's just go ahead and start here by taking care of some notes.
So lib {fmt}, this is available today for every compiler,
and the standard library header, and this is only available on Visual Studio. The next thing
that I want to talk about is how to actually print something to the screen with , so I'm
going to go ahead and switch over to Visual Studio so that we can a little bit swap back and forth on
these things. So let's go ahead and include the header. Now I just want to do a very
simple output, and you've probably already seen this before in a previous episode of C++ Weekly,
but we don't actually have any way with std to send output to the console,
so that's a little disappointing and you end up having to do something kind of like this,
which ends up being very disappointing really. So there is a slightly better way to do this
and it's kind of like this, but you end up just feeling bad after you've done this.
Uh, it's perfectly valid and legal. We're getting a character string pointer to the
std::string that was produced by the call to std , sending that to std put string (puts),
and we get, "Hello 42" printed. Now keeping in mind I have full optimizations enabled, um,
well Visual Studio, shall we say, seems to be generating a fair bit more code than it needs to.
I'm not entirely sure why or what's going on here - it looks like considerable amount of
data tables. So we're just not going to focus on that too much, but this code should make you sad.
With lib {fmt} on the other hand...
well, at the moment I'm getting a linker error for this, but we're not going to blame
any of the libraries or our compiler or anything like this. This is probably just a configuration
issue with Visual Studio on Compiler Explorer and trying to execute the binary
with the library, but we have fmt::print and as we can see this does compile,
it just doesn't execute at the moment in the context in which we are testing this.
We have this handy 'print' function from lib {fmt}, but our std header
doesn't get this until C++23. Okay, so the next thing can be looked at
as both good and bad depending on your perspective. Our header
moves with the C++ standard and it is ABI stable. Depending on what you're looking for
this could be very important to you.
On the other hand the standalone lib {fmt}
is constantly being improved with bug fixes, performance fixes; there are updates available.
As far as I know it does not have guaranteed ABI stability, but I could be wrong about that. I'm
pretty sure that it does not have guaranteed ABI stability, so that
might be a concern for you, again, depending on your perspective. Now, a kind of nebulous
concept, but coming back to the 'print' function is that lib {fmt} has a lot more utility built in,
it's simply a bigger library and so there's more helpers and more things that you might
want from it. Now the eighth and final thing that I want to mention about lib {fmt}
might surprise you a little bit. So I'm going to switch compilers again and we'll give this a test.
So here we go, we can actually do a 'constexpr' compile time formatting
of a string, and that is not something that is possible with the standard library version of
. Now I did actually use this particular feature in my talk from CppCon of 2021 called
"Your New Mental Model for constexpr', but we can see that this is clearly just calling 'puts' with
these bytes that are right here. It's not a very long string or anything, and it works quite well,
and we can also see that if we made a string that is too long to actually fit in this format_to then
we're going to get a compile time error. So you don't have to worry about, you know, buffer or
overruns or anything like that in this particular example. Now there is a quick change here that
I would like to make just to prove a point. So this is still the same except we see that we have
9992 zeros following the end of the string, so you can see here that if I took off that 'static'
then I actually do a copy of the data into the local stack; and this is exactly what the point
of that episode "Stop Using 'constexpr' (And Use This Instead!)" was all about, was that we
if we have a 'constexpr' local value we probably want it to be 'static'; but then I also want to
point out that if I remove 'constexpr' from this entirely that I do still actually see
the formatting of the string happening here. So even though the function is 'constexpr'
the compiler is not choosing to do this at compile time. If I want this, I pretty much
want to do the 'constexpr static auto' thing here, and now there is the conversations that we've had
in the past on this channel about forcing work at compile time and you can go back and look at those
to make sure you get a deeper understanding of these things, but yeah, the conclusion ultimately:
So if you're an environment where you have to use only the standard library provided things
and you have a compiler that's new enough that you actually have the std header and
can use it, then go ahead and use that. Otherwise, if you're an environment where
you do have some sort of package manager or some way to take advantage of lib {fmt},
then I think it wins in this comparison here. There's many more things to have dug into,
but I thought that it was worth talking about these differences; so thanks for watching this
episode of C++ Weekly. You know what to do subscribe, thumbs up, all the things.