1

ビット インデックスの配列を 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 に制約を追加する必要がありますか?

この関数を書き直して具象型を使用できることはわかっていますが、可能であれば汎用のままにしたいと考えています。

4

2 に答える 2

3

動作させるには、もう少しセットアップが必要になる場合がありますgetOptionSet

protocol OptionBitShiftable: IntegerLiteralConvertible {
    func << (lhs: Self, rhs: Self) -> Self
    func |= (lhs: inout Self, rhs: Self)
}
extension Int64: OptionBitShiftable {}
extension UInt64: OptionBitShiftable {}
//...

上記のものを使用すると、次のように書くことができますgetOptionSet

func getOptionSet<T: OptionSet where T.RawValue: OptionBitShiftable>(bitIndexes: [T.RawValue]) -> T {
    var result: T.RawValue = 0
    for index in bitIndexes {
        result |= 1 << index
    }
    return T(rawValue: result)
}

使用法:

struct MyOptionSet: OptionSet {
    var rawValue: Int64
    init(rawValue: Int64) {
        self.rawValue = rawValue
    }
}
let myOption: MyOptionSet = getOptionSet(bitIndexes: [1,2,3,5,7])
print(myOption.rawValue) //->174(=2+4+8+32+128)

または、次のように初期化子を定義できます。

extension OptionSet where RawValue: OptionBitShiftable {
    init(bitIndexes: [RawValue]) {
        var result: RawValue = 0
        for index in bitIndexes {
            result |= 1 << index
        }
        self.init(rawValue: result)
    }
}

次のように使用できます。

let alsoMyOption = MyOptionSet(bitIndexes: [4, 6])
print(alsoMyOption.rawValue) //->80(=16+64)
于 2016-07-15T13:34:15.410 に答える