Swift泛型中Decimal类型除法运算符缺失问题咨询
泛型代码中Double与Decimal除法运算报错的原因及解决办法
问题场景
编写泛型代码在Double和Decimal类型间切换,基于Decimal遵循的所有协议(为Double遵循协议的子集)实现了generic_calc_1,该函数可正常执行加减乘运算;但实现包含除法的generic_calc_2时,编译器报错:binary operator '/' cannot be applied to two 'T' operands。
代码示例
泛型加减乘函数(可正常运行):
func generic_calc_1<T: Comparable & CustomStringConvertible & Decodable & Encodable & ExpressibleByFloatLiteral & ExpressibleByIntegerLiteral & Hashable & Plottable & Sendable & SignedNumeric & Strideable>(a: T, b: T) -> T { return (a + b) * (b - a) } print("Calc1: Double:", generic_calc_1(a: Double(2), b: Double(3))) print("Calc1: Decimal:", generic_calc_1(a: Decimal(2), b: Decimal(3)))
泛型除法函数(报错):
func generic_calc_2<T: Comparable & CustomStringConvertible & Decodable & Encodable & ExpressibleByFloatLiteral & ExpressibleByIntegerLiteral & Hashable & Plottable & Sendable & SignedNumeric & Strideable>(a: T, b: T) -> T { return a / b //error: binary operator '/' cannot be applied to two 'T' operands }
原因解析
SignedNumeric协议不包含除法定义:当前泛型约束中的SignedNumeric仅定义了+、-、*三种运算符,并未提供除法运算符的保证,因此编译器无法确认T类型支持/运算。- Double与Decimal的除法协议不统一:Double遵循
BinaryFloatingPoint(继承自FloatingPoint),Decimal遵循DecimalFloatingPoint,这两个协议都定义了除法,但它们并未被包含在当前的泛型约束里,编译器无法识别两者的公共除法能力。
解决办法
方法1:添加FloatingPoint约束
由于BinaryFloatingPoint和DecimalFloatingPoint都继承自FloatingPoint协议,而该协议包含除法运算符定义,因此将泛型约束替换为包含FloatingPoint即可(FloatingPoint已涵盖SignedNumeric的能力,可移除SignedNumeric):
func generic_calc_2<T: Comparable & CustomStringConvertible & Decodable & Encodable & ExpressibleByFloatLiteral & ExpressibleByIntegerLiteral & Hashable & Plottable & Sendable & FloatingPoint & Strideable>(a: T, b: T) -> T { return a / b }
方法2:自定义除法协议
如果不想依赖FloatingPoint协议,可以自定义一个要求实现除法的协议,让Double和Decimal遵循该协议:
// 自定义协议,要求实现除法运算符 protocol Divisible { static func / (lhs: Self, rhs: Self) -> Self } // 让Double和Decimal遵循该协议 extension Double: Divisible {} extension Decimal: Divisible {} // 更新泛型约束,添加Divisible func generic_calc_2<T: Comparable & CustomStringConvertible & Decodable & Encodable & ExpressibleByFloatLiteral & ExpressibleByIntegerLiteral & Hashable & Plottable & Sendable & SignedNumeric & Strideable & Divisible>(a: T, b: T) -> T { return a / b }
内容的提问来源于stack exchange,提问作者nilgirian
相关产品推荐
相关产品推荐

