I've been using the FixedWidthIntger.*ReportingOverflow methods so much to safely detect wraparound in my iterators (to return nil on first overreach), I wonder if we can be more direct and take advantage of Swift's nil processing.
precedencegroup CheckedMultiplicationPrecedence {
higherThan: AdditionPrecedence
lowerThan: BitwiseShiftPrecedence
associativity: none
assignment: false
}
precedencegroup CheckedAdditionPrecedence {
higherThan: RangeFormationPrecedence
lowerThan: MultiplicationPrecedence
associativity: none
assignment: false
}
infix operator *? : CheckedMultiplicationPrecedence
infix operator /? : CheckedMultiplicationPrecedence
infix operator %? : CheckedMultiplicationPrecedence
infix operator +? : CheckedAdditionPrecedence
infix operator -? : CheckedAdditionPrecedence
extension FixedWidthInteger {
/// Returns the product of the two given values, emitting `nil` in case of
/// any overflow.
@inlinable
public static func *? (lhs: Self, rhs: Self) -> Self? {
let result = lhs.multipliedReportingOverflow(by: rhs)
return result.overflow ? nil : result.partialValue
}
/// Returns the quotient of the two given values, emitting `nil` in case of
/// any overflow.
@inlinable
public static func /? (lhs: Self, rhs: Self) -> Self? {
let result = lhs.dividedReportingOverflow(by: rhs)
return result.overflow ? nil : result.partialValue
}
/// Returns the remainder of the two given values, emitting `nil` in case of
/// any overflow.
@inlinable
public static func %? (lhs: Self, rhs: Self) -> Self? {
let result = lhs.remainderReportingOverflow(dividingBy: rhs)
return result.overflow ? nil : result.partialValue
}
/// Returns the sum of the two given values, emitting `nil` in case of any
/// overflow.
@inlinable
public static func +? (lhs: Self, rhs: Self) -> Self? {
let result = lhs.addingReportingOverflow(rhs)
return result.overflow ? nil : result.partialValue
}
/// Returns the difference of the two given values, emitting `nil` in case
/// of any overflow.
@inlinable
public static func -? (lhs: Self, rhs: Self) -> Self? {
let result = lhs.subtractingReportingOverflow(rhs)
return result.overflow ? nil : result.partialValue
}
}
You can use them like:
let two, five, sixtyfour: Int8
two = 2
five = 5
sixtyfour = 64
two +? five // 7
two -? five // -3
two *? five // 10
five /? two // 2
five %? two // 1
// All of these return `nil`
sixtyfour *? five
sixtyfour /? 0
sixtyfour %? 0
Int8.min /? -1
sixtyfour +? sixtyfour
sixtyfour -? Int8.min
Instead of using them straight like the above, you'll likely use them with constructs like "guard let", etc. At the time the various "&???" wrapping operators were added, were operators like the above considered to be added as counterparts?
Instead of separate precedence levels, should we let them use the existing MultiplicationPrecedence and AdditionPrecedence? Would we have to add overloads that take one Optional<Self> operand, and an extension for "Optional where Wrapped: FixedWidthInteger" to make overloads when both operands are Optional?