The main issue is that Numeric doesn't support generic divisions. One possible solution is to provide multiple generic methods to support different protocols (Integer/FloatingPoint) and Decimal as well:
extension Decimal {
var number: NSDecimalNumber { self as NSDecimalNumber }
var double: Double { number.doubleValue }
}
struct Percentage<T: Numeric> {
let value: T
let total: T
func percentage<F: BinaryFloatingPoint>() -> F where T: BinaryFloatingPoint {
F(value) / F(total)
}
func percentage<F: BinaryFloatingPoint>() -> F where T: BinaryInteger {
F(value) / F(total)
}
func percentage<F: BinaryFloatingPoint>() -> F where T == Decimal {
F(value.double) / F(total.double)
}
func percentage() -> Decimal where T == Decimal {
value / total
}
}
let percentageInt = Percentage<Int>(value: 10, total: 100)
let result1: Double = percentageInt.percentage() // 0.1
let percentageDouble = Percentage<Double>(value: 10, total: 100)
let result2: Double = percentageDouble.percentage() // 0.1
let result3: CGFloat = percentageDouble.percentage() // 0.1
let percentageDecimal = Percentage<Decimal>(value: 10, total: 100)
let result4 = percentageDecimal.percentage() // 0.1 decimal
let result5: Double = percentageDecimal.percentage() // 0.1