我想寫一個幫助函數,它將位索引數組轉換爲符合OptionSet的類。將位索引數組轉換爲OptionSet
func getOptionSet<T: OptionSet>(bitIndexes: [Int64]) -> T {
var result: Int64 = 0
for index in bitIndexes {
result |= 1 << index
}
return T(rawValue: result) // error
}
這無法編譯:
Cannot invoke initializer for type 'T' with an argument list of type '(rawValue: Int64)'
我也嘗試使用RawValue:
func getOptionSet<T: OptionSet>(bitIndexes: [T.RawValue]) {
var result = T.RawValue() // error
這並不工作,以及:
Cannot invoke value of type 'T.RawValue.Type' with argument list '()'
能這樣做?我是否需要在T上增加額外的約束條件?
我知道有可能重寫這個函數來使用具體的類型,但是我想盡可能保持它的通用性。
謝謝,這非常有用。是否值得將所有內容轉換爲32位平臺的UIntMax還是不是問題?讓結果:UIntMax = bitIndexes.reduce(UIntMax(0)){UIntMax($ 0)| UIntMax(1)<< UIntMax($ 1)} – Zmey
@Zmey:即使在32位平臺上,OptionSet類型也可以具有64位的RawValue。如果中間值僅爲32位,則會丟失位。但你不需要'UIntMax($ 0)'或'UIntMax(1)',這些類型是自動推斷的。 - 其實我從中可以看出編輯歷史中的錯誤。現在應該是正確的。 –
@Zmey:中間結果/累加器也可以具有RawValue類型。問題是左移運算符<< <<沒有在(Un)SignedInteger協議中定義,所以你必須爲所有可能的原始類型定義額外的協議擴展,我試圖避免這種擴展。 - 在這個答案的修訂1中,我通過乘法而不是左移解決了這個問題。所以這是可能的,但我發現這個代碼更優雅。 –