Adding unsigned and signed integers

Today I had a really simple problem: add a signed and unsigned number of the same size. No solution I (and rkruppe on #rust) found were 100% satisfactory:

  • unsigned.wrapping_add(signed as usize): Doesn't panic when unsigned overflows like normal addition in debug. Eg 0usize.wrapping_add(-1isize as usize) won't panic.
  • (unsigned as isize + signed) as usize: Panics in debug if the signed addition overflows, even though that would not have overflown the unsigned integer. Also like the above, it doesn't panic if the unsigned value overflows negatively.
  • if signed < 0 { unsigned -= -signed as usize; } else { unsigned += signed as usize; }: Long code is long. Also, it cannot be used as an expression in the same way the prior two solutions can.

I can of course create a function that does all the necessary checks, but shouldn't something like this be part of the standard library (or even standard operators)?

20 comments · 94% upvoted · other discussions

comments

[deleted]

[deleted]

Noctune [OP]

Wrapping is necessary because negative values result in values that will wrap when added due to two's complement. For example -1isize as usize == usize::max_value(). So 1usize.wrapping_add(usize::max_value()) == 0usize. It's still different from the unsigned value overflowing, like if you add 0usize and -1isize.