Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RemiBardon/3f32f41b118c4ef39984a35ada7699e0 to your computer and use it in GitHub Desktop.
Save RemiBardon/3f32f41b118c4ef39984a35ada7699e0 to your computer and use it in GitHub Desktop.
Swift – Member not found when accessing a value through two conditional subscripts
// MARK: - CRS
protocol CoordinateReferenceSystem {
associatedtype CoordinateComponents
}
protocol TwoDimensionsCRS: CoordinateReferenceSystem where CoordinateComponents == (X, Y) {
associatedtype X
associatedtype Y
}
protocol GeographicCRS: CoordinateReferenceSystem {}
protocol GeocentricCRS: CoordinateReferenceSystem {}
enum WGS84Geographic2DCRS: TwoDimensionsCRS, GeographicCRS {
typealias X = Double
typealias Y = Double
}
// MARK: - Coordinates
@dynamicMemberLookup
protocol Coordinates<CRS> {
associatedtype CRS: CoordinateReferenceSystem
typealias Components = CRS.CoordinateComponents
var components: Components { get }
subscript<T>(dynamicMember keyPath: KeyPath<Components, T>) -> T { get }
}
extension Coordinates {
subscript<T>(dynamicMember keyPath: KeyPath<Components, T>) -> T {
self.components[keyPath: keyPath]
}
}
protocol TwoDimensionsCoordinates: Coordinates where CRS: TwoDimensionsCRS {
var x: CRS.X { get }
var y: CRS.Y { get }
}
extension TwoDimensionsCoordinates {
var x: CRS.X { self.components.0 }
var y: CRS.Y { self.components.1 }
}
extension TwoDimensionsCoordinates where CRS: GeographicCRS {
var latitude: CRS.X { self.x }
var longitude: CRS.Y { self.y }
}
struct Coordinates2D: TwoDimensionsCoordinates {
typealias CRS = WGS84Geographic2DCRS
var components: Components
}
// MARK: - Points
@dynamicMemberLookup
protocol Point<C, Metadata> {
associatedtype C: Coordinates
associatedtype Metadata
var coordinates: C { get }
var metadata: Metadata { get }
subscript<T>(dynamicMember keyPath: KeyPath<C, T>) -> T { get }
}
extension Point {
subscript<T>(dynamicMember keyPath: KeyPath<C, T>) -> T {
self.coordinates[keyPath: keyPath]
}
}
// Doesn't change anything
//extension Point where C.CRS: GeographicCRS {
// subscript<T>(dynamicMember keyPath: KeyPath<C, T>) -> T {
// self.coordinates[keyPath: keyPath]
// }
//}
struct Point2D {
typealias Metadata = Void
var coordinates: Coordinates2D
var metadata: Metadata
}
// MARK: - Code playground
let point = Point2D(coordinates: .init(components: (2, 3)), metadata: ())
let l1 = point.coordinates.latitude
// error: value of type 'Point2D' has no member 'latitude'
let l2 = point.latitude
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment