Hello, and welcome to C++ weekly.
I'm your host, Jason Turner.
I'm available for code reviews, contracting,
and on-site training.
In this episode, I'm going to discuss a new feature in C++20,
and then explain perhaps some at least potential use cases
for it.
So let's just start here.
I've got GCC trunk.
I am on compiler explorer, as I usually am.
I am currently compiling in C++17 mode,
if you can see that here, with wall, wextra, and wpedantic.
And that's by far not all of the warnings that are available,
just for the record.
Wall doesn't come anywhere close to all of them.
Neither does wextra.
So I'm going to create a struct.
And I'm going to give it a virtual member function.
And I'm going to make it pure virtual.
Now if I wanted this member function
to be accessible in a constexpr context,
I need to add constexpr here.
And when I do, we should get a warning here from the compiler.
Warning, member get value cannot be declared both virtual
in constexpr in C++17 mode, is effectively what it is saying
here.
But it can be in C++2A mode.
So if I switch this to 2A, then this
is going to compile without any warning.
Just for a little bit of completeness here,
we might want to make this no discard, because it's often
an error to ignore the return value from a const member.
And we'll make this const, something like that.
Now that's a lot of words.
But it accurately shows what we want to do here.
Now I'm going to make a derived, and make this return 5.
And now we have a compiling.
We had to match the function signature.
And that's good, we got exactly what we wanted out of it.
Now let's go ahead and make a different derived object
type like this.
So we've got one that returns 5 and one that returns 10.
Now you might be wondering why in the world would
I want a virtual function to be constexpr.
And I find often in teaching C++ and constexpr,
that largely people think, well, I have no reason to do that
at compile time.
And it's entirely possible that you
don't have any particular reason do this at compile time.
But don't limit your imagination on this.
There are lots of things currently in your project
right now, I promise, that could be done at compile time.
And if runtime is of great concern to you,
you should be moving more things to compile time that you can.
That does have the potential to slow down your compile times.
But you just have to decide what's
the most important aspect of your project.
So how and why might we use this in a compile time context?
Let's see if we can come up with something.
So I've created a handful of very poorly named objects.
And now I am going to put them in an array by pointer.
Now I'm not going to suggest that this is a best
practice or anything like this.
But I am doing this to illustrate an idea.
Now if I had not put these in here by pointer,
I would be in a situation where I
was slicing each of these things off to the base type,
and that's definitely not what I want.
And we should sprinkle some const in here for good measure,
because const makes everything better when
we can use it appropriately.
Now we need to include the array header.
So I have this very simple framework
now of a couple of derived types and a thing
containing some data.
And now I want to do this at compile time.
So I'm doing this because I can't use make unique yet
in a constexpr context.
And also there's just no reason to create these things
on the heap when I know the exact number and types
of objects in here.
And you might, with a little bit of imagination,
see some other way to do this.
But let's go ahead and see if we can sum these values up.
So we are getting an interesting warning from GCC in this case.
And this is an experimental feature,
since C++20 hasn't been released yet.
It's complaining that I have an inline member function--
and constexpr implies in line in this case--
that is used but never defined.
And it is pure virtual in this case.
So it is true that using the inline keyword
here doesn't make a lot of sense.
But constexpr does make this possible.
And it is possible with C++20 to say I want to create some
heterogeneous set of data that's using inheritance and base
classes, and pass these around in some way,
and operate on those virtual functions in a compile time
constexpr context.
So that's what the future gives us.
Now GCC currently supports this whether or not
we have 2A mode turned on.
And Clang does not yet support it.
And I do not believe Visual Studio does yet either.
But it's maybe something to start you thinking about how
you might apply different constexpr techniques when you
do get C++ 20 available to you.
So thanks for watching this episode of C++ Weekly,
and I hope you enjoyed it.