On 28/11/2018 10:01, Emil Dotchevski wrote:
Same is true about signed/unsigned implicit conversions. Do you want a warning in this case?
Yes. They are not compatible types, and so conversion should be treated with suspicion by default. As should hopefully be obvious, implicit narrowing conversions are never a good idea. Everyone recognises that conversion from intN_t to uintM_t or from uintN_t to intM_t where N > M is a narrowing conversion, and this should have a warning. This is not controversial. Similarly everyone's happy that conversion from uintN_t to intM_t where N < M is *not* a narrowing conversion and this can be done implicitly, with no warning. What is less obvious and more controversial but is still true: conversion from intN_t to uintM_t or uintN_t to intM_t where N = M is *also* a narrowing conversion (both ways), because there are values in one that are not expressible in the other. This is *slightly* better than the first case because the conversion is at least perfectly reversible -- there is no loss or problem if you convert, store, and then convert back before use -- as long as you never try to use the value in the "wrong" type, or you have sufficient assurance that the actual value falls within the common range of both types. (An assert helps, but only if it happens to be hit with the bad input in a debug build where someone reports the failure. Which will not catch all cases.) And similarly intN_t to uintM_t where N < M is still always a narrowing conversion, for the entire range of negative values. The conversion is "safe" only if you have assurance that you don't have a negative value. (Or if you do have a negative value and you're trying to do bit-twiddling for performance reasons with an appropriate algorithm, which generally assumes 2's complement representation and thus relies on implementation-defined behaviour. Much safety is sacrificed on the altar of performance. But even there it can and should be explicit about the casting, since that doesn't impact performance.)
I know, but it is still a valid question to ask what is the role of the cast. Does it make the program more readable? In what way is your version preferable?
It's an assurance (at least in theory) that someone is changing the type intentionally rather than unintentionally. It's the exact same reason that people are encouraged to make conversion constructors and operators explicit, especially for potentially narrowing conversions.
You keep saying the original code is unsafe. How is the implicit conversion less safe than the cast?
See above. One shows intent, the other does not.