У меня есть несколько protocols
для vectors
, используемых в моем приложении.У них есть default implementations
в extensions
, так что я могу реализовать все дополнительные функции для всех types of vectors
.Теперь я хотел бы расширить SIMD3
на Scalar == Double
, чтобы реализовать протокол 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, но тогда мне нужно было бы отдельно реализовать ее для всех других типов, соответствующих вектору.Я использую это также для SCNVector3
и CGPoint
.Я не знаю что лучше.Может быть, есть какое-то лучшее решение, чтобы я мог реализовать его для всех других типов, кроме SIMD3?