My actual question is bigger than that, but operators are the bulk of the practical problem.
Use case: There are a bazillion things you might want to do with 2-vectors. And there isn't a single standard for them, even when their scalars are Double
s. We've got CGPoint
, CGVector
, CGSize
, and probably a bunch I don't know about. You could define a protocol like this…
/// A type that can operate with other types via intermediate conversion.
public protocol CommonOperable {
/// The type to be converted to, for interoperability.
associatedtype Operand
init(_: Operand)
var convertedToOperand: Operand { get }
}
extension CommonOperable {
/// Forwards operators to converted operands.
static func operate<Operable1: CommonOperable, Result: CommonOperable>(
_ operable0: Self,
_ operate: (Operand, Operand) -> Operand,
_ operable1: Operable1
) -> Result
where Operand == Operable1.Operand, Operand == Result.Operand {
Result(
operate(
operable0.convertedToOperand,
operable1.convertedToOperand
)
)
}
}
…and define all of their Operand
s to be SIMD2<CGFloat.NativeType>
. With that, you could save some duplication…
public extension CommonOperable
where Operand: SIMD, Operand.Scalar: FloatingPoint {
static func + <Operable1: CommonOperable, Result: CommonOperable>
(operable0: Self, operable1: Operable1) -> Result
where Operand == Operable1.Operand, Operand == Result.Operand {
operate(operable0, +, operable1)
}
static func + (operable0: Self, operable1: Self) -> Self {
operate(operable0, +, operable1)
}
static func += <Operable1: CommonOperable>
(operable0: inout Self, operable1: Operable1)
where Operand == Operable1.Operand {
operable0 = operable0 + operable1
}
//MARK:-
static func - <Operable1: CommonOperable, Result: CommonOperable>
(operable0: Self, operable1: Operable1) -> Result
where Operand == Operable1.Operand, Operand == Result.Operand {
operate(operable0, -, operable1)
}
static func - (operable0: Self, operable1: Self) -> Self {
operate(operable0, -, operable1)
}
static func -= <Operable1: CommonOperable>
(operable0: inout Self, operable1: Operable1)
where Operand == Operable1.Operand {
operable0 = operable0 - operable1
}
//MARK:-
//...😐
}
…but that's still terrible. What's better? Ideally, all those CG
types could be SIMD
s, but I don't think that's the way?