【问题标题】:SIMD3 Extension with default implementations具有默认实现的 SIMD3 扩展
【发布时间】:2019-08-24 17:54:53
【问题描述】:

我有几个protocols 用于我的应用程序中的vectors。他们在extensions 中有一些default implementations,因此我可以为所有types of vectors 实现所有附加功能。现在我想用Scalar == Double 扩展SIMD3,以实现Vector3D 协议。 Swift 告诉我,如果我在扩展中指定 Scalar 的类型,那么我还需要为此类型添加 Vector3D 的所有依赖项。我不知道为什么当我选择SIMD3 的关联类型时这不会自动发生,但是没关系。所以现在我有这样的东西:

import UIKit
import simd

protocol DividableByInt {
    static func / (lhs: Self, rhs: Int) -> Self
}
protocol HasBasicinitializer {
    init()
}
protocol BasicMathOperations {
    static func + (lhs: Self, rhs: Self) -> Self
    static func - (lhs: Self, rhs: Self) -> Self
    static func * (lhs: Self, rhs: Self) -> Self
    static func / (lhs: Self, rhs: Self) -> Self
}
protocol Vector: BasicMathOperations, DividableByInt, HasBasicinitializer {
    associatedtype Scalar: (SIMDScalar & FloatingPoint)
    static var zero: Self { get }
    static func calculate(_ lhs: Self, _ rhs: Self, _ operation: (Scalar, Scalar) -> Scalar) -> Self
    static func calculate(_ lhs: Self, _ rhs: Scalar, _ operation: (Scalar, Scalar) -> Scalar) -> Self
    func allAxesValues() -> [Scalar]
}
extension Vector {
    static func + (lhs: Self, rhs: Self) -> Self { return calculate(lhs, rhs, +) }
    static func - (lhs: Self, rhs: Self) -> Self { return calculate(lhs, rhs, -) }
    static func * (lhs: Self, rhs: Self) -> Self { return calculate(lhs, rhs, *) }
    static func / (lhs: Self, rhs: Self) -> Self { return calculate(lhs, rhs, /) }
    static func * (lhs: Self, rhs: Scalar) -> Self { return calculate(lhs, rhs, *) }
    static func / (lhs: Self, rhs: Scalar) -> Self { return calculate(lhs, rhs, /) }
    static func / (lhs: Self, rhs: Int) -> Self { return calculate(lhs, Scalar(rhs), /) }
}
protocol Vector3D: Vector {
    init(x: Scalar, y: Scalar, z: Scalar)
    var x: Scalar { get }
    var y: Scalar { get }
    var z: Scalar { get }
}
extension Vector3D {
    func allAxesValues() -> [Scalar] {
        return [x, y, z]
    }
    static func calculate(_ lhs: Self, _ rhs: Self, _ operation: (Scalar, Scalar) -> Scalar) -> Self {
        return Self(x: operation(lhs.x, rhs.x), y: operation(lhs.y, rhs.y), z: operation(lhs.z, rhs.z))
    }
    static func calculate(_ lhs: Self, _ rhs: Scalar, _ operation: (Scalar, Scalar) -> Scalar) -> Self {
        return Self(x: operation(lhs.x, rhs), y: operation(lhs.y, rhs), z: operation(lhs.z, rhs))
    }
}

extension SIMD3: Vector3D where Scalar == Double {}

extension SIMD3: HasBasicinitializer {}
extension SIMD3: DividableByInt where Scalar == Double {}
extension SIMD3: Vector where Scalar == Double {
    static let zero = SIMD3(x: 0.0, y: 0.0, z: 0.0)
}
extension SIMD3: BasicMathOperations where Scalar == Double {}

一切都会自动运行,除了最后一件事:

extension SIMD3: BasicMathOperations where Scalar == Double {}

编译器说:

Type 'SIMD3<Scalar>' does not conform to protocol 'BasicMathOperations'

但是自从我添加了

extension SIMD3: Vector where Scalar == Double 

它应该已经实现了所有需要的方法,并且能够继续。协议DividableByInt 的继承方式几乎相同,它可以与Vector extension 的实现一起使用。为什么BasicMathOperations 不能使用Vector extension 中实现的方法?

我知道我可以通过添加来解决这个问题

extension SIMD3: BasicMathOperations where Scalar == Double {
    static func + (lhs: SIMD3, rhs: SIMD3) -> SIMD3 { return calculate(lhs, rhs, +) }
    static func - (lhs: SIMD3, rhs: SIMD3) -> SIMD3 { return calculate(lhs, rhs, -) }
    static func * (lhs: SIMD3, rhs: SIMD3) -> SIMD3 { return calculate(lhs, rhs, *) }
    static func / (lhs: SIMD3, rhs: SIMD3) -> SIMD3 { return calculate(lhs, rhs, /) }
}

但我不想加倍这段代码,因为它已经在 extension Vector 中实现,应该从那里使用它。

最后我只想扩展SIMD3 来实现Vector3D。如果需要 Scalar == Double 或任何可能的标量类型。


看起来问题是因为 SIMD3 已经实现了 +、-、/、* 等函数,编译器无法确定选择哪一个。我可以从Vector 中删除默认实现,这将解决 SIMD3 的问题,但是我需要为符合 Vector 的所有其他类型单独实现它。我也将它用于SCNVector3CGPoint。我不知道什么更好。也许有一些更好的解决方案,这样我就可以为除 SIMD3 之外的所有其他类型实现此功能?

【问题讨论】:

    标签: swift protocols generic-programming swift-protocols swift5


    【解决方案1】:

    好的,我想我找到了一个更好的解决方案。我将BasicMathOperations 的默认实现从extension Vector 移动到单独的协议,然后我将这个新协议的继承添加到所有符合Vector 的类型,除了SIMD3。

    // Adds default implementation for BasicMathOperation
    protocol VectorWithDefaultImplementationForBasicMathOperations: Vector {}
    
    extension VectorWithDefaultImplementationForBasicMathOperations {
        static func + (lhs: Self, rhs: Self) -> Self { return calculate(lhs, rhs, +) }
        static func - (lhs: Self, rhs: Self) -> Self { return calculate(lhs, rhs, -) }
        static func * (lhs: Self, rhs: Self) -> Self { return calculate(lhs, rhs, *) }
        static func / (lhs: Self, rhs: Self) -> Self { return calculate(lhs, rhs, /) }
    }
    
    extension CGPoint: VectorWithDefaultImplementationForBasicMathOperations {}
    extension SCNVector3: VectorWithDefaultImplementationForBasicMathOperations {}
    

    如果有人知道更好的解决方案,请告诉我,但我认为这已经很好了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      相关资源
      最近更新 更多