2014-11-03 33 views
5

我正在嘗試編寫一個需要位移操作的通用函數。我得到了我不明白的行爲。這是一個簡單的函數來演示問題。快速通用函數中的位移

func testBytes<T: IntegerType>(bytesIn: [UInt8], inout dataOut: T){ 

let outputSize = sizeof(T) 
var temp: T = 0 
dataOut = 0 
temp = bytesIn[0] as T 
temp = temp << 1 

} 

如果我這樣做,那麼最後一行在xcode中給我一個錯誤「T is not convertible to Int」。

我最後一行更改爲temp = temp << (1 as T)

然後此行的錯誤更改爲「T是無法轉換爲UINT8」

無論這些錯誤消息之一在這方面道理給我。我能做些什麼來啓用一個泛型類型的位移?

回答

7

我有一個blog post on this topic即進入更多細節,但本質上有三個步驟:

  1. UInt8創建位移操作符的新協議和構造:

    protocol BitshiftOperationsType { 
        func <<(lhs: Self, rhs: Self) -> Self 
        func >>(lhs: Self, rhs: Self) -> Self 
        init(_ val: UInt8) 
    } 
    
  2. 聲明符合每種整數類型的擴展名 - 容易,因爲它們已經實現了所有內容BitshiftOperationsType

    extension Int : BitshiftOperationsType {} 
    extension Int8 : BitshiftOperationsType {} 
    extension Int16 : BitshiftOperationsType {} 
    extension Int32 : BitshiftOperationsType {} 
    extension Int64 : BitshiftOperationsType {} 
    extension UInt : BitshiftOperationsType {} 
    extension UInt8 : BitshiftOperationsType {} 
    extension UInt16 : BitshiftOperationsType {} 
    extension UInt32 : BitshiftOperationsType {} 
    extension UInt64 : BitshiftOperationsType {} 
    
  3. 添加通用約束等等T符合您的新的協議:

    func testBytes<T: IntegerType where T: BitshiftOperationsType>(bytesIn: [UInt8], inout dataOut: T){ 
        let outputSize = sizeof(T) 
        var temp: T = 0 
        dataOut = 0 
        temp = T(bytesIn[0]) 
        temp = temp << 1 
    } 
    

感謝Martin R.用於修復總比特我收到了這裏!

+2

我已經準備了類似的答案,但你更快:-)。我所做的解決第二個問題的方法是在協議中添加init(_val:UInt8)。所有(有符號和無符號)整數類型都有這樣的構造函數,所以你可以用'temp = T(bytesIn [0])'進行轉換,並且只需要一個實現。 – 2014-11-03 15:43:51

+0

偉大的修復!用這個改變更新了答案。 – 2014-11-03 15:48:52

+0

謝謝一堆。我可能會很快提出一個關於潛在問題的新問題,因爲泛型可能不是我尋找的優雅答案。 – dustincarr 2014-11-03 15:57:28