Hello and welcome to C++ Weekly. I'm your host, Jason Turner. I am available for
code reviews and on-site training. In this episode I'm going to give you another
C++ homework assignment. This is the one that you probably expected to come
along eventually, and that is of course "'constexpr' All The Things."
I am starting here with the example that I last left off on in our "'const' All of The Things"
episode, so our three homework assignments up to this point will have been "'auto' All The Things,"
"'const' All the Things," and "'constexpr' All of The Things."
You are free to start with your previous homework assignment source code if you would like to.
You are also free to start with the pt example that I have been illustrating from
since the beginning of these homework assignments - that is this the "smallpt:
Global Illumination in 99 lines of C++" code. It generates this image.
We will have a couple of things to talk about in this "'constexpr' All The Things" episode,
but you can see the 99 lines here; and now just a recap - you can go and click on the raw file
and copy this, and just paste it straight into Compiler Explorer. If you do paste it straight
into Compiler Explorer here I do recommend that again we've got C++ 20 -Wpedantic, -Wall,
-Wextra, -Wconversion, possibly -Werror. If you do -Werror straight away it is not going to compile.
You probably want to remove this pragma for OMP but you don't have to, and you can
format this real quick and see that it's actually more like a 145 line program if you want it to
actually be readable. We want to 'constexpr' all the things, and for this one, with any project
that you're working on I do suggest that you start from the top. We're just going to say,
"Okay, can this constructor be 'constexpr'? Yeah, in fact, you know what? It can be 'constexpr',"
and we can do that with most of these member functions looking at this particular example.
What is going to be very interesting to observe, particularly if you start with
the smallpt example, is that the more things you make 'constexpr' the more you can observe
the Compiler Explorer window here going from what is currently basically
all code to more and more of it becoming data as you make things 'constexpr';
and that holds whether or not you are compiling with optimizations enabled. So if I get to a
point where 'spheres' here is a 'constexpr' object that is static, then I can be at -O0,
and I'm going to see a large pre-calculated data table at the bottom of this binary.
So that's something to play with. Now because we do know - see this is the set of spheres - we do
know the entire geometry of the scene. It is in fact entirely possible for this entire program
to be executed at compile time and then just to write the PPM out at runtime. That is
100% possible here, but it's going to take work. To get ALL the way there is actually going to take
a LOT of work, and I will give you a little spoiler alert right here, this square root
function - go and ask yourself, "Do you currently have a square root function available to you that
is 'constexpr'?" That's something you might have to find or implement on your own, and that is just
one of the functions that is going to come up when you go to do this. So I didn't really talk a whole
lot about 'constexpr'. A 'constexpr' function is a function that can be executed at compile time;
a 'constexpr' variable is a value that is probably going to be calculated at compile time.
There's some weasel words in the standard there - doesn't actually have to be calculated at compile
time unless it is used at compile time. So if it is unobservable to you whether or not it was
calculated at compile time, the compiler is free to not actually calculate a constexpr variable
at compile time; but static constexpr variables are ALWAYS calculated at compile time,
so that's why I mentioned this 'spheres' here being static. Now because it is a global variable,
if I make it 'constexpr' it is naturally going to be static - that is its lifetime is the
lifetime of the program. So that part's already kind of taken care of us here for this thing.
This would be a really interesting exercise - can you get this so that the entire scene is rendered
at compile time and then you just write it out to image.ppm at runtime? And if you, you know,
you're going to have to tweak a few things. You're almost certainly going to have to change the size
of the image that's calculated. This number of samples that is done for each pixel - you're
going to have to hard code that. That can't be based on the parameters passed in to 'argv',
but once you hard code those things (which is totally allowed in here), then you're going
to have to sort out the rest of the things that limit (or not) our ability to make this
entirely compile time. There's some random number generators in here. If you've been watching this
show for a while, you will know that there are, in fact, constexpr random number generators. I
have written several of them. You can find them in previous episodes and find links hidden throughout
my repositories and gists and whatnot on GitHub, so check those out for some help if you want to.
I will also tell you that there are, in fact, some constexpr math libraries that are out there. They
are relatively easy to find by Googling, and you will probably not be very surprised when you
find out who has worked on them. So yeah, that is how 'constexpr' all the things for this example,
if you're going to use smallpt for this homework exercise, is going to look. If you use your own
code, then that is fine as well of course; but again have fun with this. If you want to submit
your results and share what you have learned I will put a place in the official C++ Weekly GitHub
repository where you can submit your results here as a pull request. So thank you for watching,
again, this episode of C++ Weekly. Make sure you subscribe. The next homework assignment will be
coming up in a couple of weeks, and I hope really that you are learning things from these exercises.