Auto and static_casts are good practice

In Scott Meyer's book, Effective Modern C ++, we can read that:

std::vector<bool> features(const Widget& w); Widget w; … bool highPriority = features(w)[5]; … processWidget(w, highPriority); 

and parameter with auto

 auto highPriority = features(w)[5]; 

which causes undefined behavior, because features() returns std::vector<bool> , which uses an Object proxy of type std::vector<bool>::reference when returning values ​​from opearator[] .

As a solution to this, it is recommended not to stop using auto , but to use static_casts .

So Scott Meyers advises using:

 auto highPriority = static_cast<bool>(features(w)[5]); 

instead:

 bool highPriority = features(w)[5]; 

My question is: What is the difference between the two? In my opinion, both of them are the same, because both methods make refactoring more difficult in exactly the same way (changing the type of the return value in the functions of the function does not make the highPriority variable another type), and the second is shorter for writing.

+5
source share
3 answers

If you don't like the features interface, you can hide the ugliness in the helper function

 bool is_high_priority(const Widget& w) { return features(w)[5]; } 

and now your

 auto highPriority = is_high_priority(w); 

works as expected.

+7
source

With features function that returns std::vector<bool> ,

 auto highPriority = features(w)[5]; 

stored logical link. A saved object refers to a vector that no longer exists. Using it, Undefined Behavior arises.

Instead of this

 bool const highPriority = features(w)[5]; 

or

 auto const highPriority = !!features(w)[5]; 

or, as Scott recommends; but this is too verbose for my taste - use static_cast .

The saved object is now bool .

There is no functional difference between these three ways of expressing the same declaration. The only differences are non-functional: in my opinion, the unnecessary verbosity of static_cast and the possibility of that !! can suppress a stupid performance warning from one common compiler.

+5
source

When you use auto, auto prints it as the type returned by highPriority, which is a reference to bool. The fact is that highPriority does not return a link to bool, but to a std :: vector :: reference object. ('reference' is a nested class inside std :: vector). std :: vector :: reference is a "proxy class", a class that emulates the behavior of some other type. This is not only the proxy class, but also the "invisible" proxy class. Such classes do not work with cars. Auto cannot correctly infer the type of an invisible proxy class. But static_cast forces the high priority conversion to bool. This avoids undefined behavior.

0
source

Source: https://habr.com/ru/post/1233232/


All Articles