top of page
Andrea

The implicit importance of explicit

While coding some basic stuff, I ran into a strange bug.

To be fair, it looked strange to my (then) ignorant eyes.


Let's say I had a simple class for representing 2D vectors:

I was then checking the validity of a Vector* variable, but distractedly dereferenced it while checking, so I wrote something like

Now, what I actually found very weird was that the condition was being evaluated as true and the branch being executed.

How could it be? A Vector instance was NULL? Huh?

So, instead of simply correcting the obvious dereferencing bug, I investigated on what the hell was happening.


First of all, I changed NULL to its modern C++11 nullptr counterpart:

to examine its behavior.

In this case, the compiler gave me an error: Invalid operands to binary expression ('Vector' and 'nullptr_t').

The problem became clearer: I would expect an error when trying to compare a Vector instance with an int (NULL is 0), but I wasn't getting it. Instead, 0 was implicitly cast as a Vector.


Being *vec_ptr a Vector with both x and y set to 0 (because of default values in the constructor arguments), I also knew that 0 is somehow evaluated as such a Vector.

So I tried to assign it to a Vector variable just to be sure:

Unsurprisingly, this was a correct assignment.

Finally, the lightbulb moment arrived: I remembered I had read some advice by Bjarne Stroustrup about always declaring as explicit any constructor that can be called with a single argument.

I overlooked that advice at the time and didn't even considered this was the case, because Vector's constructor takes in 2 arguments and not one.

This was a stupid consideration by my side, since the constructor provides default arguments, thus allowing being called with zero, one or two arguments.

At this point, I declared the constructor as explicit and this solved the issue.


Turns out I was lucky: thanks to a trivial and careless mistake, I learned my lessons well:

  1. Declare as explicit any constructor that can be called with a single argument

  2. Don't compare pointers to NULL, use nullptr

Thanks, Bjarne!

Comments


bottom of page