Hello and welcome to C++ Weekly. I'm your host Jason Turner. I'm available for on-site training,
code reviews and contracting. Now, this is the fourth episode
in our series on learning modern C++ by using the tools that are available to you
effectively; and we are in Visual Studio. I suggest that you go back and listen to
Episodes 1 & 2 for how we got the set up for this and why we are using
Visual Studio.
In this episode, I'm just gonna pick up where we last left off, and I'm going to
talk about const and constexpr a little bit, and we're going to see what other tools
can tell us about that. Now in the last episode we had our 'derived' and 'base',
and this all ended up becoming rather complicated to do everything correctly.
That was by following the rules that our Tidy (Clang-Tidy) was giving back to us,
which was great. It helped us get all the gotchas. But we also have this 'unique' pointer here,
and if you are an astute observer you may have noticed that I did not use make_unique. That is
partially on purpose. Part of the problem is that I was creating a 'derived' and returning
a 'base' object, which is one reason why Clang-Tidy didn't catch it for us; but the
other thing is that I really was just trying to steer you away from using heap allocations
because this is not something that we like to do. If we keep things on the stack,
the compiler can optimize it better, and that's better. So we have this thing,
and we realize it's pretty much
over engineered. So let's just go ahead and flatten this all out. We don't have any need
for this. We have our data member, and we have our 'do_thing'; and we will put the 'do_thing' here,
and we'll get rid of this. You can see all along the way that the compiler is
telling us what we have done wrong very quickly. (Intellisense is here from Visual
Studio.) We have something that's 'override' that doesn't override, so we will get rid of that;
and then we have this thing that is called 'derived' that doesn't exist anymore.
So now we have 'Type', and let's just go ahead and give this a slightly more meaningful name...
So we've got our object, and we're calling our function on it. Now let's
go ahead and run this through Clang-Tidy and Cppcheck and
see what we get. I'm going to go ahead and remove that line.
This is some of the areas where Cppcheck really shines compared to
other functions. It has this "do_thing can be made a static function",
and this is a very interesting comment. It says, "Making a
function static can bring a performance benefit since there's no 'this' instance."
So it is entirely correct. Since this is not operating on any member data
we can just make this static and that's still going to compile
exactly the same; and the compiler may be able to do a more efficient things
with it because it knows that it doesn't need to care about the 'this' pointer.
But let's say that this is maybe not fair. What we really wanted to do for
this 'do_thing' is return our current data value plus 4, something like this
just to make use of our local data. So we're not modifying anything. We're just doing this;
and we will rerun this now with Cppcheck. Now Cppcheck is telling us making this function
const is what we want to do and that's right. That's good. We should make all
of our member functions const when possible, and so this is great.
It's teaching us to use const where we should, and to use
static when possible. so let's add our 'do_other_thing',
and just for the sake of testing here, let's see if Clang-Tidy gives us any other information.
So there's no warnings from Clang-Tidy, but one thing that we can learn here that our
tools are not yet able to teach us is that this really could be constexpr.
There's no reason to not make this function constexpr, all of our data types and our
structure currently are trivial and this can work. So we have just done that, and maybe this is just,
this is one of those things where the tools cannot
yet teach us what we need to be doing to write our code as good as possible.
So we've got our object 'type', and we've made our members constexpr and const, and
now let's call them, and we're going to do that with 'argc'.
So we say "if argc > 1 then we call 'do_thing'," and otherwise we call 'do_other_things'.
So we'll go ahead and run this through Cppcheck again and see if it teaches us anything else.
So let's see what Cppcheck tells us - we have here that Cppcheck says it has found the same
code in 'if' and the related 'else' block. "This is suspicious and might be a cut and
paste or logic error;" and wow, that's great, it really was. We really meant to
call 'do_other_thing', so Cppcheck caught that for us. Now, we realize actually,
what we didn't mean to do here for this code was to call it in the case
that argc was greater than 1. Let's go ahead and satisfy our tools like this.
What we meant to say is "if the sizeof(long) > 4",
so in this case we're saying effectively "is 'long' a 64-bit
or a 32-bit in this code." Let's see what our tools can give us for this.
So for this one we are going to go ahead and build our solution with Visual Studio. And now
we have this warning that was recently added in Visual Studio that says "Conditional expression
is constant. Consider using 'if constexpr' statement instead." So out of curiosity,
let's see if our other tools can catch this. So this warning here
is the one that is still from Visual Studio - we can tell because it says C4127 that's its code;
and this one is the one that is coming from Clang-Tidy,
and it just says consider replacing 'long' with 'int32', so that's uh...
Well, if we replaced 'long' with 'int32', then we know that it would never be greater than 4;
and we're trying to test something out here. So if we make this 'if
constexpr' then we can satisfy Visual Studio. It's the only tool that I'm aware of right now
that will tell us when things could be a const expression in an 'if constexpr' kind of way,
and this is helpful because it is actually guaranteed to only compile the given block
of code if the const expression is true; instead of if it's a regular 'if' then
it's something that is almost certainly compiled away, but not a hundred percent guaranteed to be.
So that wraps up our episode for now as far as what our tools can teach
us about our const members and using 'if constexpr' and constexpr members.
Be sure to subscribe. Follow me on Twitter, and check out any of the links below.