2016-06-21 63 views
2

我執行斯威夫特二維矢量結構:如何在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 {} 

此代碼編譯。現在我想添加一個轉換初始化程序以允許轉換例如Vec2<Int>Vec2<Float>。我說這Vec2

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

和所需初始化到Numeric協議:

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

然而,這引起我是無法解決的錯誤:

不能使用類型爲'(T2)'的參數列表調用類型爲'T'的初始化程序

overloop這些部分匹配的參數列表存在'T'的廣告:(Int),(Double),(Float)

任何想法?

+0

的問題(對欺騙問題略有不同,但我不知道它值得一個單獨的答案)是你的協議不能保證每一個具體類型符合'Numeric'由您在要求中列出的初始者處理。因此,你必須做一些事情來爲協議添加一個'影子'功能要求,以保證每一種類型都實現自己的轉換邏輯 - 我在回答上述鏈接問題時詳細說明了這一點。 – Hamish

+0

@ originaluser2謝謝,解決了它! – emlai

+0

高興地幫助:) – Hamish

回答

1

_asOther'影子'功能解決方案出現here工作。萬一任何人的興趣,這裏的最終代碼:

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) } 
}