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?)

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

社区洞察

其他会员也浏览了