2016-06-21 9 views
2

Ich bin eine 2D-Vektor-Struktur in Swift Umsetzung:Wie implementiert man den generischen Konvertierungsinitialisierer in Swift?

public struct Vec2<T: Numeric> { 
    public let x: T 
    public let y: T 

    public init(_ x: T, _ y: T) { 
     self.x = x; 
     self.y = y; 
    } 

    // ... 
} 

public protocol Numeric: Equatable { 
    // ... 
} 

extension Int: Numeric {} 
extension Double: Numeric {} 
extension Float: Numeric {} 

Dieser Code kompiliert wird. Nun möchte ich einen Konversionsinitialisierer hinzufügen, um z.B. a Vec2<Int> zu Vec2<Float>. Ich fügte hinzu, dies zu Vec2:

public init<T2: Numeric>(_ other: Vec2<T2>) { 
     self.x = T(other.x) 
     self.y = T(other.y) 
    } 

und die benötigten Initialisierungen zum Numeric Protokoll:

init(_: Int) 
    init(_: Double) 
    init(_: Float) 

Dies ist jedoch ein Fehler verursacht, dass ich nicht in der Lage bin zu lösen:

kann nicht Initialisierer für Typ 'T' mit einer Argumentliste vom Typ '(T2)' aufrufen

überladen Anzeigen für 'T' existieren mit diesen teilweise übereinstimmenden Parameterlisten: (Int), (Double), (Float)

Irgendwelche Ideen?

+0

Das Problem (etwas anders als die Betrogene Frage, aber ich bin nicht sicher, ob es eine separate Antwort garantiert) ist, dass das Protokoll nicht, dass jede konkrete Art, die garantieren kann, Übereinstimmung mit "Numerisch" wird von den Initialisierern behandelt, die Sie in den Anforderungen aufgelistet haben. Sie müssen daher so etwas wie das Hinzufügen einer "Schatten" -Funktionsanforderung zum Protokoll durchführen, um zu gewährleisten, dass jeder Typ seine eigene Konvertierungslogik implementiert - was ich in meiner Antwort auf die oben verlinkte Frage ausführe. – Hamish

+0

@ originaluser2 Danke, das hat es gelöst! – emlai

+0

Gerne helfen :) – Hamish

Antwort

1

Die _asOther 'Schatten' -Funktion Lösung präsentiert here gearbeitet. Nur für den Fall, dass jemand interessiert ist, hier ist der endgültige Code:

public struct Vec2<T: Numeric> { 
    public let x: T 
    public let y: T 

    public init(_ x: T, _ y: T) { 
     self.x = x; 
     self.y = y; 
    } 

    public init<T2: Numeric>(_ other: Vec2<T2>) { 
     self.x = other.x._asOther() 
     self.y = other.y._asOther() 
    } 

    // ... 
} 

public protocol Numeric: Equatable { 
    init(_: Int) 
    init(_: Double) 
    init(_: Float) 
    func _asOther<T: Numeric>() -> T 
    // ... 
} 

extension Int: Numeric { 
    public func _asOther<T: Numeric>() -> T { return T(self) } 
} 

extension Double: Numeric { 
    public func _asOther<T: Numeric>() -> T { return T(self) } 
} 

extension Float: Numeric { 
    public func _asOther<T: Numeric>() -> T { return T(self) } 
}