3 ms·
> In well-behaved code I would expect this to be an unreachable condition because you are explicitly checking for sensible inputs before doing this type of arit
by MauranKilom 5y ago
> In well-behaved code I would expect this to be an unreachable condition because you are explicitly checking for sensible inputs before doing this type of arithmetic
You previously claimed "there will never be undefined behavior [by using unsigned types]", but now you also require that the UB scenario is checked beforehand? I'm confused how you conclude unsigned types to be safer than signed ones ("no UB") when you require UB be ruled out in the first place.
Unless you explicitly intend for wraparound to happen, your program has a bug on overflow regardless of signedness. You can (and possibly should) guard against the situation, but that favors neither side.
> Assuming an integer is signed can be much less safe in practice because there is often no guarantee that an integer type is always signed or unsigned in a given context. [...]
That is not an argument for or against using signed types. If types change from under you, you have a host of other issues anyway (as you say). Mixed sign comparisons, unexpected promotions, overflows... You get the exact same issues whether you yourself favor signed or unsigned types when mixing them with (what are, in your description) effectively unknown types. So again, your argument against signed types appears to be "you have to be careful either way", which gives zero reasons to favor unsigned over signed types.
- jandrewrogers 5y agoUnsigned types have an absolute advantage for unsigned values: they have twice the range. This turns out to have useful performance advantages e.g. in large data infrastructure software. In typical C++ metaprogramming for this type of software, the integer types for processing code paths are often generated using the most compact primitive type because it is expected that billions of instances of these types may be in memory and trillions in storage, and there are multiple integer types where the required range of values for each are interdependent. A considerable amount of design in database engines, for example, goes into maximizing scalability while minimizing the total footprint of integer type instances. This is a function of the expressible non-negative range of the types, and cutting it in half will cause some of the types to be promoted, doubling their footprint. It is difficult enough to squeeze them into unsigned types without a step change in integer size as it is. That overflows are well-defined, in contrast to UB, has value in cases of bugs because the consequences of the bug will be well-defined and less subject to clever compiler optimizations.