On Thu, Sep 4, 2025 at 12:58 PM Julien Villemure-Fréchette via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
> Why? Because it's the choice that doesn't result in information loss when overflow occurs.

AFAIK, arithmetic overflow is exactly means that bits of information were lost during the calculation. [...]

What Brian means is that the "mod 2^N" operation distributes over addition, distributes over subtraction, and distributes over multiplication.
Whether you do the "mod 2^N" operation immediately after each binary operator, or only once at the end of the whole expression, you'll get the same answer.
So in this sense, doing a lot of extra "mod 2^N" operations as part of each binary operator is "value-preserving" because it doesn't interfere with the value you get at the end.
    (((a + b) \mod 2^{32}) - c) \signedmod 2^{32} = (a + b - c) \signedmod 2^{32}
    (((a \times b) \mod 2^{32}) + c) \signedmod 2^{32} = (a \times b + c) \signedmod 2^{32}

But this nice property doesn't extend to division.

Thus ARM, for example, can get away with a single 32x32=32 multiplication instruction (`MUL`) but requires two distinct 32x32=32 division instructions (`SDIV` and `UDIV`).
https://developer.arm.com/documentation/ddi0597/2025-06/Base-Instructions/

Now, philosophically I'd disagree that this property makes wrapping arithmetic any "safer" than, say, saturating arithmetic, or reliably aborting the program on overflow, or generating a C++ exception on overflow. Wrapping arithmetic might even create a moral hazard, by usually but not always giving the right answer. But wrapping arithmetic is certainly convenient and performant at the physical level, yeah, and it makes perfect sense that an industry codebase might just set `-fwrapv` in their project file and happily forget all about integer-overflow-is-UB for years at a time. (I am not aware of any industry codebases that have done that, but I'm sure it has been done somewhere.)

–Arthur