C++ tidbit #3: Contextual Conversion

C++ tidbit #3: Contextual Conversion

Warmup: explicit constructors

When you mark a cast operator as explicit:

struct C {

   explicit operator bool() { return true; }

};        

(yes, that is a silly implementation) you're saying that implicit casts will fail to compile:


bool b1 = c;                     // error

bool b2 = c==true;               // error

bool b3 = static_cast<bool>(c);  // explicit cast - success        

This is generally considered a good practice, as implicit casts are a gaping hole in C++ strong-type system. If, for example, you passed a wrong argument to a function - you want the compiler to err and help you catch it, and not implicit-cast to hide away the source of the error and sneak up on you in surprising ways later.

Some Surprises

So, what happened in the 2nd line here?


if (c == true) {}    // compilation error, as expected

if (c)  {}           // success ?!        

And here??


while(c) {}                // success !?

for (int i=0; c ; ++i) {}  // success !?!        

And, oh my, here?


bool b4 = c || false         // success !!?

bool b5 = c ? true : false;  // success !??!        

No explicit casts are anywhere to be seen. Shouldn't all these implicit casts be forbidden??

You can fiddle with this live code in various compilers here.

Enter Contextual Conversion

`bool` is special.

There are specific locations within the C++ syntax that require a bool type. In all the surprise-success cases above, `c` appears in such a place (go check!).

In these places a slightly different set of rules kicks in, and the term employed is contextual conversion (not casting!) to bool. In a nutshell: existing cast-operators to bool are considered, with `explicit` ignored. Details and some delicate diffs between C++ versions here.

Final Musing

This is a fine example of a good intention on the road to hell. Sometime during C++'s evolution, its designers wished to provide this convenience to developers - and not have them type out casts to bool where it would seem clear from the context that such a cast must be present.

I would happily trade the extra head-scratches this had caused me for some extra typing and reading. The same goes for many, many other C++ dark corners too. Some modern languages (notably Rust) learnt that lesson well, and allow no implicit casting of any kind.

Kobi Kai Calev

Signal Processing and Software Engineer | Motivated by creating value for the end user | Interested in fault tolerance and flexibility of software | Keen language learner and language transmission activist

2 年

OMG! The horror! Thanks for highlighting this nuance(?) (read: nuisance?)

要查看或添加评论,请登录

社区洞察

其他会员也浏览了