使Swift泛型与重载函数一起玩
我正在尝试构建一个通用类型MyStruct< T>可以使用Float或Double进行内部存储.在初始化程序中,我传递了一个类型为T的参数(我打算将其作为Float或Double).该初始化程序调用一些trig函数,例如sin()和cos().这两个函数都在系统库中重载,以提供Float和Double版本.
var f:Float=1.2 var d:Double=1.2 sin(f) //0.9320391 sin(d) //0.9320390859672263 麻烦的是,我不能在我的通用结构中使用它们.精简案例如下所示: struct MyStruct<T> { var v:T init(x:T){v=sin(x)} } 因为:
看起来应该有办法使这项工作,但它感觉很像this situation.评论表明,没有办法要求存在全局功能. 我可以通过使用如下构造强制这种情况: init(x:T){v=T(sin(Double(x)))} 并且在T上设置一个可以从Double构造的约束,但这似乎打败了构造结构的Float版本的目的,这是为了减少在关键代码循环中使用它时的计算工作量. 如果在库中将sin()定义为泛型函数而不是重载函数,感觉会更容易: func sin<T:FloatingPointType> (x:T) -> T 但是它就是这样啊. 有没有办法让我在标准库之上构建一个Float / Double不可知的库,而不会增加很多开销? 解决方法
不幸的是,没有简单的方法可以像在Swift中实现sin()一样.它必须被视为运算符(如Equatable和==如何工作),以便允许您将其添加为协议要求.
@matt’s solution是一个很好的快速修复,但如果你想要一些更永久的东西,你可能想要考虑创建一个协议,然后扩展浮点类型,以便允许你使用泛型版本重载sin()函数. protocol FloatingPointMathType : FloatingPointType { var _sinValue : Self { get } } extension Float : FloatingPointMathType { var _sinValue : Float {return sin(self)} } extension Double : FloatingPointMathType { var _sinValue : Double {return sin(self)} } extension CGFloat : FloatingPointMathType { var _sinValue : CGFloat {return sin(self)} } func sin<T:FloatingPointMathType>(x:T) -> T {return x._sinValue} (随意添加更多数学函数) 我们必须在这里使用’shadow’计算属性来弥补我们不能简单地使用sin()作为协议要求的事实.它并不理想 – 但可能和你一样好. 您现在可以继续使用sin()作为通用函数: struct MyStruct<T:FloatingPointMathType> { var v : T init(x:T) { v = sin(x) } } print(MyStruct(x: Float(3.0)).v) // 0.14112 print(MyStruct(x: Double(3.0)).v) // 0.141120008059867 print(MyStruct(x: CGFloat(3.0)).v) // 0.141120008059867 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |