Я пытаюсь написать вспомогательную функцию, которая преобразует массив бит-индексов в класс, соответствующий 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?
Я знаю, что эту функцию можно переписать, чтобы использовать конкретный тип, но я хочу сохранить его, если это возможно, общий.
Спасибо, это очень полезно. Стоит ли отличать все от UIntMax для 32-битных платформ или это не проблема? let result: UIntMax = bitIndexes.reduce (UIntMax (0)) {UIntMax ($ 0) | UIntMax (1) << UIntMax ($ 1)} – Zmey
@Zmey: Тип OptionSet может иметь 64-битный RawValue даже на 32-битных платформах. Если промежуточное значение составляет 32 бит, вы теряете биты. Но вам не нужны 'UIntMax ($ 0)' или 'UIntMax (1)', эти типы выводятся автоматически. - Вообще-то я сделал это неправильно между вами, как вы можете видеть из истории изменений. Теперь это должно быть правильно. –
@Zmey: промежуточный результат/аккумулятор также может иметь тип RawValue. Проблема в том, что оператор с левым сдвигом '<<' не определен в протоколе (Un) SignedInteger, поэтому вам нужно будет определить дополнительные расширения протокола для всех возможных исходных типов, чего я пытался избежать. - В ревизии 1 этого ответа я решил, что умножением вместо левого сдвига. Так что это возможно, но я нашел этот код более элегантным. –