2016-06-21 4 views
2

나는 스위프트의 2D 벡터 구조체를 구현 해요 :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) 

을, 이것이 내가 해결할 수있어 오류가 발생합니다 :

수 없어 'T (T2)'형식의 인수 목록을 사용하여 'T'유형의 이니셜 라이저 호출

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