使用受限 RawValue 扩展 OptionSet 的正确方法

The right way to extend OptionSet with a constrained RawValue

我有一个 OptionSet,我希望能够对其执行按位运算(BitwiseOperation 协议中的操作)。我为我的类型写了一个扩展,然后意识到我应该让它成为可重用的代码。花了一段时间才想出办法,我所做的是制作一个继承自两个协议的协议并在关联类型上添加约束,然后是提供默认实现的协议扩展。

它有效,但我的问题是:这是完成此任务的最佳方法吗?

protocol BitwiseOptionSet : BitwiseOperations, OptionSet {
    associatedtype RawValue : BitwiseOperations, ExpressibleByIntegerLiteral
}
extension BitwiseOptionSet {
    static var allZeros : Self {
        return Self(rawValue: 0)
    }
    prefix static func ~(x: Self) -> Self {
        return Self(rawValue: ~x.rawValue)
    }
    static func ^(lhs: Self, rhs: Self) -> Self {
        return Self(rawValue: lhs.rawValue ^ rhs.rawValue)
    }
    static func &(lhs: Self, rhs: Self) -> Self {
        return Self(rawValue: lhs.rawValue & rhs.rawValue)
    }
    static func |(lhs: Self, rhs: Self) -> Self {
        return Self(rawValue: lhs.rawValue | rhs.rawValue)
    }
}

您可以扩展 OptionSet 并限制其 RawValue:

extension OptionSet where RawValue: BitwiseOperations {
    static var allZeros : Self {
        return Self(rawValue: .allZeros)
    }
    prefix static func ~(x: Self) -> Self {
        return Self(rawValue: ~x.rawValue)
    }
    static func ^(lhs: Self, rhs: Self) -> Self {
        return Self(rawValue: lhs.rawValue ^ rhs.rawValue)
    }
    static func &(lhs: Self, rhs: Self) -> Self {
        return Self(rawValue: lhs.rawValue & rhs.rawValue)
    }
    static func |(lhs: Self, rhs: Self) -> Self {
        return Self(rawValue: lhs.rawValue | rhs.rawValue)
    }
}

请注意,要求符合 ExpressibleByIntegerLiteral 可以通过使用 Self(rawValue: .allZeros) 而不是来避免 Self(rawValue: 0).

示例:

struct MyOptionSet: OptionSet {
    let rawValue: UInt16
    init(rawValue: UInt16) {
        self.rawValue = rawValue
    }
}

let a = MyOptionSet(rawValue: 3)
let b = MyOptionSet(rawValue: 5)
let c = a & b
print(c.rawValue) // 1