Edit: I have restated and hopefully clarified this question over here. Now I've added the solution.
I've defined a function (see foo()
in attached example) as a default function for struct
s adopting my protocol
. It applies the +
operator defined in respect of two other variables which themselves adopt other protocols
and +
is defined in one of those protocols. The variables are typed using associatedtype
s.
I get the message:
Binary operator '+' cannot be applied to operands of type 'Self.PointType' and 'Self.VectorType'
If I implement the function inside my struct
(see bar() in attached) it works so I'm sure my + operator does work.
My example is pared down to the minimum needed to work in a playground. Just remove the comments in the LineProtocol extension
to get the error. It seems to me that Self.PointType
is a Point
and Self.VectorType
is a Vector
.
To be clear: The reason I used associatedtype
s is because many different struct
s adopt each of the three protocols in the example so I can't name them directly
public protocol PointProtocol {
associatedtype VectorType: VectorProtocol
var elements: [Float] { get set }
}
extension PointProtocol {
public static func +(lhs: Self, rhs:VectorType) -> Self {
var translate = lhs
for i in 0..<2 { translate.elements[i] += rhs.elements[i] }
return translate
}
}
public protocol VectorProtocol {
associatedtype VectorType: VectorProtocol
var elements: [Float] { get set }
}
public struct Point: PointProtocol {
public typealias PointType = Point
public typealias VectorType = Vector
public var elements = [Float](repeating: 0.0, count: 2)
public init(_ x: Float,_ y: Float) {
self.elements = [x,y]
}
}
public struct Vector: VectorProtocol {
public typealias VectorType = Vector
public static let dimension: Int = 2
public var elements = [Float](repeating:Float(0.0), count: 2)
public init(_ x: Float,_ y: Float) {
self.elements = [x,y]
}
}
public protocol LineProtocol {
associatedtype PointType: PointProtocol
associatedtype VectorType: VectorProtocol
var anchor: PointType { get set }
var direction: VectorType { get set }
}
extension LineProtocol {
// public func foo() -> PointType {
// return (anchor + direction)
// }
}
public struct Line: LineProtocol {
public typealias PointType = Point
public typealias VectorType = Vector
public var anchor: PointType
public var direction: VectorType
public init(anchor: Point, direction: Vector) {
self.anchor = anchor
self.direction = direction
}
public func bar() -> Point {
return (anchor + direction)
}
}
let line = Line(anchor: Point(3, 4), direction: Vector(5, 1))
print(line.bar())
//print(line.foo())
Solution adapted from @Honey's suggestion: replace extension with:
extension LineProtocol where Self.VectorType == Self.PointType.VectorType {
public func foo() -> PointType {
// Constraint passes VectorType thru to the PointProtocol
return (anchor + direction)
}
}