swift - 让 Swift 泛型玩转重载函数

标签 swift generics

我正在尝试构建通用类型 MyStruct<T>可以使用 FloatDouble用于内部存储。在初始化程序中,我传递了一个 T 类型的参数(我打算将其设为 FloatDouble )。该初始化程序调用一些三角函数,例如 sin()cos() .这两个函数都在系统库中重载以提供 FloatDouble版本。

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)}
}

因为:

Playground execution failed: Untitled Page.xcplaygroundpage:9:17: error: cannot invoke 'sin' with an argument list of type '(T)' init(x:T){v=sin(x)}

Untitled Page.xcplaygroundpage:9:17: note: overloads for 'sin' exist with these partially matching parameter lists: (Float), (Double) 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== 的工作方式),以便您可以将其添加为协议(protocol)要求。

@matt's solution是一个很好的快速修复,但如果你想要更永久的东西,你可能需要考虑创建一个协议(protocol),然后扩展浮点类型,以便允许你重载 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}

(欢迎添加更多数学函数)

我们必须在这里使用“影子”计算属性来弥补我们不能简单地使用 sin() 作为协议(protocol)要求的事实。这并不理想,但可能与您将要获得的一样好。

您现在可以继续将 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

关于swift - 让 Swift 泛型玩转重载函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37369649/

相关文章:

java - 具有可变类型参数的泛型

ios - AVCapturePhotoOutput jpegPhotoDataRepresentation 访问预览照片

ios - 如何使用 Core Data 允许歌曲在播放列表中重新排列?

ios - 快速从核心数据中获取会导致崩溃,因为我收到了其他类型的对象

swift - 如何在 Swift 中声明类型化的字典?

java - 使用泛型 Java 对数组/比较器进行二分搜索

java - 泛型参数的实例

swift - 关闭 SwiftUI 中的选择器并将选择器选择重置为初始值

java - 使用 Java 泛型确保接收到的参数与类或其子类型相同

java - Spring 4 不会自动限定 Autowiring 上的泛型类型