2016-06-14 2 views
3

그래서 SpriteKit을 사용할 때 CGPoint, CGVectorCGSize을 제대로 처리하려고합니다. 이들 모두는 수직 및 수평 구성 요소 (벡터)가있는 구조체입니다. 나는 3 구조체를 확장 물론 VectorType'! ='연산자를 모호하게 사용합니다.

protocol VectorType { 
    init(x: CGFloat, y: CGFloat) 

    var x: CGFloat { get set } 
    var y: CGFloat { get set } 
} 

이 프로토콜을 준수하고 각 구조체 즉의 수평 및 수직 성분 x 반환 CGVector에 대한 dxxy를 연결하는 (에 대한 같은 : 그래서 프로토콜을 만들어 설정), xCGSize의 경우 width을 반환하고 CGPoint의 경우 해당 값을 그대로 사용하므로 확장명을 비워 둡니다.

이제 "주"연산자 (+ - * / ...)가 오버로드되었으므로 쉽게 캐스팅하거나 새 객체를 만들지 않고도 여러 유형의 구조체와 관련된 작업을 수행 할 수 있습니다. 그러나 여기에서 중요한 것은 또한 오버로드 된 것입니다. 이 같은 등가 운영자 :

이제
//Compiler requires me to use generics for some reason 
func == <T: VectorType, U: VectorType> (lhs: T, rhs: U) -> Bool { 
    return (lhs.x == rhs.x) && (lhs.y == rhs.y) 
} 

func != <T: VectorType, U: VectorType> (lhs: T, rhs: U) -> Bool { 
    return !(lhs == rhs) 
} 

,이 코드의 모든 것이 != 운영자를 제외하고 괜찮 테스트 할 때. 이러한 연산자를 테스트하기 위해 크기, 벡터 크기 및 크기를 점과 비교하여 각 유형에 대해 비교합니다. ==을 사용할 때 아무런 문제가 없습니다. 내가 !=를 사용할 때

Equal operator test

하지만, 문제가 있습니다. 이 같은 Ambiguous use of operator '!=' 있습니다 :

Not equal operator test

이 어디에서 오는 나는 완전히 얻을 : CGVector to CGVector, CGPoint to CGPointCGSize to CGSize 이미 존재 비교 ==!= 운영자 오버로드. 이것들은 다음과 같이 선언됩니다.

@warn_unused_result func ==(lhs: CGSize, rhs: CGSize) -> Bool 

모든 종류의 과부하가 있습니다. 따라서 모호성이 어디서 발생하는지 알아보고, 같은 유형을 비교할 때 어떤 연산자를 사용할 지 알지 못합니다. 그러나 우리가 기본적으로 동일한 상황을 가지고 있다면 testEqual()== 연산자와 같은 문제가없는 이유를 이해할 수 없습니다.

필자는 컴파일러 버그 인 것 같지만 잘 모르겠다. 프로젝트 정리, Xcode 재시작 및 새 프로젝트 만들기를 시도했지만 여전히 작동하지 않는다. 또한 Found this candidate을 선택하는 모호성을 유발하는 다른 선언을 보려고하면 아무 것도 표시되지 않습니다.

그래서 문제는 어떻게 작동시킬 수 있습니까? 또는 다른 작동 방식을 제안 할 수 있습니까? (다른 작동기를 만드는 것을 포함하지 않습니다)?

업데이트

내가 사용하고 실제로 ==!= 구현이 실제로 다르게 선언 된 것을 발견했다.이것은 사용되는 == 과부하가 AFAIK이 또한 내 선언과 충돌한다

@warn_unused_result func ==(lhs: CGSize, rhs: CGSize) -> Bool 

을 선언하는 방법이지만, 분명히하지 않습니다.

여기에 다른 != 오버로드 선언이 있습니다.

@warn_unused_result func !=<T : Equatable>(lhs: T, rhs: T) -> Bool 
lhs 이후

rhs 및 동일한 형태를 가지며 VectorType 프로토콜에 따르는 세 종류 Equatable이 과부하가 동작을위한 후보 부합.

나는 그것을 명시 적으로 CGVector, CGPoint 또는 CGSize A에 대한 요구, 그리고 아마도 그 제네릭을 통해 우선합니다 때문에 == 사용됩니다 같아요. 두 == 운영자가 충돌하지 않는 이유를 알고 계신지 확실하지 않습니다.

+1

'! ='정의를 덮어 쓰지 않으면 어떻게 될까요? 'not =='을 기본으로하는 기본 구현을 가지고 있습니다. – Alexander

+0

BTW 자신의 유형에'CG' 접두어를 사용하지 마십시오. 그것은 CoreGraphics에 대해 통상적으로 예약되어 있습니다. – Alexander

+0

글쎄요, 제가 할 수있을 것 같아요.하지만 기분이 좋지 않습니다. 나는 피하려고하는 것을 수동으로 비교할 필요가 있습니다.하지만 다른 해결책을 찾을 수 없다면 나는 갈거야. 그리고 네, 저는 CG 작품에 대해 생각하고 있었고, 저는 그것을 바꿀 것입니다. 작품 이름을 지었을 때 가장 먼저 생각한 것이 었습니다. – lsauceda

답변

2

유형이 Equatable 인 경우 동등 연산자 ==을 정의해야하지만 표준 라이브러리는 평등 연산자와 관련하여 부등호 연산자 !=을 제공합니다. 자신의 컴파일러에 의해 제공되는 하나

두 가지 정의가 있기 때문에

귀하의 모호성 오류는 (당신이 Equatableprotocol requirements를 보면 사실, 유일한 필수 기능은 func ==입니다). 둘 다 동일한 서명을 가지므로 컴파일러는이를 해결할 수 없습니다.

자신을 func !=으로 정의하지 마십시오. 제공된 것을 사용하십시오.

정의가 필요하다면 Equatable 유형으로 작업하지 않았을 수 있습니다.

업데이트 당신은 equatable 종류의 작업을하지 않는

. 포인트가 크기와 같은지 묻는 것은 의미가 없습니다. 귀하의 문제는 그것이 강제적으로 의미를 갖도록 시도하는 데서 비롯됩니다.

모든 유형 조합에 대해 등호 연산자를 제공하고 있습니다. 따라서 CGPoint()==CGVector(), CGPoint()!=CGVector(), CGPoint()=CGSize()CGPoint()!=CGSize()을 제공하지만 CGPoint()==CGPoint()CGPoint()!=CGPoint()을 제공하며 CoreGraphics와 충돌합니다. 왜 오류 메시지가 나타나는 지 이해하고 왜 ==이 작동하는지 이해하기 위해 계속 읽어보십시오.

평등 :

CGPoint, CGVector 및 CGSize Equatable 모두에 적합하고, 양쪽 장치가 동일한 종류 동등 연산자를 제공한다. 서로 다른 기본 유형의 경우에도,

func == <T: VectorType, U: VectorType> (lhs: T, rhs: U) -> Bool 

이 두 VectorType 객체에 작동하는 평등 연산자를 선언

당신은 다음 확장을 통해 이러한 유형에 작동하는 평등 연산자를 제공하고 있습니다.

컴파일러는 먼저 직접 일치하는 항목을 검색 한 다음 찾지 못하면 유형을 일반 항목으로 대체하여 항목을 생성하려고 시도합니다.

따라서 CGPoint()==CGPoint()이라고 말하면 CoreGraphics에서 찾은 func ==(lhs:CGPoint, rhs:CGPoint)->Bool을 찾습니다.

CGPoint()==CGVector()라고 말하면 func ==(lhs:CGPoint, rhs:CGVector)->Bool이 표시됩니다. 이것은 CoreGraphics 나 그 밖의 다른 곳에서는 정의되어 있지 않으므로 일반 정의에서 건물 1로 이동합니다.

귀하가 제공 한 : 당신의 프로토콜과 확장을 통해

func == <T: VectorType, U: VectorType> (lhs: T, rhs: U) -> Bool 

, 그것은 당신의 정의를 취하므로, 생산 CGPointTCGVectorU 대체 : 그것은 하나를 찾았다

func == (lhs:CGPoint, rhs:CGPoint) -> Bool 

(그리고 하나만 사용할 수있는 정의이므로 사용합니다.

불평등 :

당신이 그것을 정의되지 않은 func !=(lhs:CGPoint, rhs:CGPoint)->Bool를 찾습니다 CGPoint()!=CGPoint() 말한다. 그것은 일반 정의에서 하나를 빌드하는 것으로 이동합니다. 그것은 표준 라이브러리에서

func !=(lhs:T, rhs:T)->Bool 

을 찾아 생산 CGPointT 대체 : FUNC를 = (좌를 : CGPoint, 우 : CGPoint)! -> 요구 사항을 만족

BOOL

.

func !=(lhs:CGPoint, rhs:CGPoint)->Bool 

:

func != <T: VectorType, U: VectorType> (lhs: T, rhs: U) -> Bool 

그것을 얻기 위해 모두 T 및 CGPoint와 U을 대체 할 수 있습니다 (직접, 또는 Equatable를 통해) : 당신이 선언 한 때문에

, 이제는 요구 사항을 충족시키는 두 가지 방법이 있습니다. 어떤 정의를 사용해야할지 결정할 방법이 없으므로 모호성 오류로 중단됩니다.

+1

그래,! = 연산자가 필요 없다는 것을 알지 못했습니다.어쨌든 나는 그것을 정의하지 않았고 여전히 작동하지 않았다. 분명히 모호하다. 두 가지 오버로드 (코어 그래픽과 equatable에서 오는 오버로드)가 모두 사용될 수 있고 컴파일러가 혼란 스럽기 때문이다. = 어떤 이유로 든 연산자, 어쨌든 그 이유는 알고 있는지 확인하기 위해 업데이트를 읽으십시오. 나는 그것을 vector_float2로 모두 캐스팅하고 해당 유형의 연산자를 사용하여 해결했습니다. – lsauceda

관련 문제