Search code examples
swiftgenericscomputed-properties

Binary operator '/' cannot be applied to two 'T' operands


struct PickerRange<T: Comparable> {
    var start: T
    var end: T
    var step: T

    var length: T {
        // Binary operator '/' cannot be applied to two 'T' operands.
        return max(start, end) - min(start,end) / step 
    }
}

Error is generated when creating computed properties. How to fix?


Solution

  • Simply specify one of the Numeric protocols.

    For floating point precision:

    struct PickerRange<T:FloatingPoint> {
        var start: T
        var end: T
        var step: T
    
        var length: T {
            return max(start, end) -  (min(start,end) / step)
        }
    }
    

    SignedInteger, UnsignedInteger or other Numeric protocols are also an option.

    // Comparable

    Neither of these require of you to specify Comparable additionally, so specifying one of these is suffice for the case.

    EDIT:

    How to make one structure for Int and Double?

    Essentially, you can, by specifying SignedNumeric:

    struct PickerRange<T:SignedNumeric & Comparable> {
        var start: T
        var end: T
        var step: T
    }
    
    // Treated as PickerRange<Double>
    let a = PickerRange(start: 1.0, end: 5.0, step: 1)
    
    // Treated as PickerRange<Int>
    let b = PickerRange(start: 1, end: 5, step: 1)
    

    However, you have specialized length property, which includes / operator not supported by SignedNumeric. A workaround would consist in type-checking/force-casting to a type you have initialized your struct with:

    struct PickerRange<T:SignedNumeric & Comparable> {
        var start: T
        var end: T
        var step: T
    
        var length: T {
            if T.self is Double.Type {
                return (max(start, end) as! Double) - ((min(start, end) as! Double) / (step as! Double)) as! T
            } else if T.self is Int.Type {
                return (max(start, end) as! Int) - ((min(start, end) as! Int) / (step as! Int)) as! T
            } else {
                return 0
            }
        }
    }
    
    let a = PickerRange(start: 1.0, end: 5.0, step: 1)
    let b = PickerRange(start: 1, end: 10, step: 1)
    
    print(a.length)
    print(b.length)