I want to add an isize to a usize and include bounds checking so that the result does not overflow the bounds of a usize. How can this be done?
You could use a combination of isize::is_negative(), isize::wrapping_abs(), usize::checked_add() and usize::checked_sub().
const fn add(lhs: usize, rhs: isize) -> Option<usize> {
if rhs.is_negative() {
lhs.checked_sub(rhs.wrapping_abs() as usize)
} else {
lhs.checked_add(rhs as usize)
}
}
Why isize::is_negative() vs rhs < 0? In this case, it doesn't change anything, as logical operations on literals count as constant expressions.
However, while it is allowed for literals it is not allowed in general, as traits methods cannot be const. So if you had a wrapping type, e.g. Foo(isize) then it wouldn't be allowed to say foo < Foo(0) in a const context. Though, it would be possible to say foo.is_negative() as Foo could still implement a const fn is_negative().
Yes, you'd still be able to say foo.0 < 0, but that's besides the point I was trying to make.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With