首页 > 解决方案 > 使用 Swift 泛型调用非泛型库

问题描述

我正在尝试为 Accelerate vDSP 框架中的一些向量操作编写一个通用的 Swift 包装器,但我遇到了以通用方式调用函数的问题。

我的向量结构看起来像:

public struct Vector<T> {
  let array: [T]
  public static func add(_ a: [T], _ b: [T]) -> [T] {
    vDSP.add(a, b)
  }

  public static func + (_ lhs: Self , _ rhs: Self) -> Self {
    Self.add(lhs.array, rhs.array)
  }
}

问题是add函数被重载,要么采用浮点数并返回浮点数,要么采用双精度数并返回双精度数。由于在编译时类型未知,因此出现错误No exact matches in call to static method 'add'

我发现解决这个问题的唯一方法是在调用和强制转换之前显式检查类型:

public static func add(_ a: [T], _ b: [T]) -> [T] {
  if T.self is Float.Type {
    return vDSP.add(a as! [Float], b as! [Float]) as! [T]
  } else {
    return vDSP.add(a as! [Double], b as! [Double]) as! [T]
  }
}

或使用约束方法

public static func add(_ a: T, _ b: [T]) -> [T] where T == Float { vDSP.add(a, b) }
public static func add(_ a: T, _ b: [T]) -> [T] where T == Double { vDSP.add(a, b) }

这两种情况都会导致令人不舒服的代码重复,而且如果我有两种以上的类型(例如,如果为即将到来的 Float16 类型添加了支持),我需要继续添加越来越多的案例。后一种方法似乎特别糟糕,因为方法主体是相同的。

我希望能够做类似的事情,vDSP.add<T>(a, b)但似乎 Swift 不支持这一点。有没有其他方法可以实现这一点并避免代码重复?

标签: swiftgenericsvdspaccelerate

解决方案


推荐阅读