可比较的枚举与整数

4
为了比较具有Int作为原始值的枚举,我添加了以下内容:
func  <<T: RawRepresentable>(a: T, b: T) -> Bool where T.RawValue: Comparable {
    return a.rawValue < b.rawValue
}

现在我可以做到:
enum Foo: Int {
    case a = 1
    case b = 2
}

let a = Foo.a
let b = Foo.b

print(a < b) // true

但是我应该如何使枚举类型可以进行比较,例如:
print(b < 1) // error

1
你需要另一个 < 重载,其中操作数是 RawRepresentable 和 Int 吗? - matt
我一直在尝试但是失败了。谢谢你的回答! - Henny Lee
3个回答

2

您只需要做更多您已经在做的事情:

func <<T:RawRepresentable>(a:T, b:Int) -> Bool where T.RawValue == Int {
    return a.rawValue < b
}

2

稍微通用一些的版本 @matt 的解决方案 - 允许您将给定的 RawRepresentable 与其 RawValue 进行比较。请注意,您必须为 <> 实现两个重载以允许进行所有4种可能的比较组合。

func < <T : RawRepresentable>(lhs: T, rhs: T.RawValue) -> Bool where T.RawValue : Comparable {
    return lhs.rawValue < rhs
} // allows b < 1

func < <T : RawRepresentable>(lhs: T.RawValue, rhs: T) -> Bool where T.RawValue : Comparable {
    return lhs < rhs.rawValue
} // allows 1 < b

func > <T : RawRepresentable>(lhs: T, rhs: T.RawValue) -> Bool where T.RawValue : Comparable {
    return lhs.rawValue > rhs
} // allows b > 1

func > <T : RawRepresentable>(lhs: T.RawValue, rhs: T) -> Bool where T.RawValue : Comparable {
    return lhs > rhs.rawValue
} // allows 1 > b

尽管如此,我仍然会谨慎使用这种重载。能够说出类似b < 1这样的话并不是很糟糕,但当允许您说出b < c,其中c是一个Int时,情况就变得更加复杂了 - 这开始变得稍微不太清楚您实际上正在比较什么(更不用说增加了重载分辨率的额外复杂性)。
简单地说,print(b.rawValue < 1)既清晰又简洁,这也是我写代码的方式。

1

Int不是RawRepresentable,因此无法与您的<运算符一起使用。

以下是两种解决方法:

  1. Make 2 new < overloads:

    • <<T: RawRepresentable>(a: T, b: Int)
    • <<T: RawRepresentable>(a: Int, b: T)
  2. Make Int conform to RawRepresentable, and rewrite your existing < overload to use two generic types, which can be compared iff they have the same RawValue, which is itself Comparable.

    extension Int: RawRepresentable {
        public init?(rawValue: Int) { self.init(rawValue) }
        public var rawValue: Int { return self }
    }
    
    func < <T: RawRepresentable, U: RawRepresentable>(a: T, b: U) -> Bool
        where T.RawValue: Comparable, T.RawValue == U.RawValue {
            return a.rawValue < b.rawValue
    }
    
    enum Foo: Int {
        case a = 1
        case b = 2
    }
    
    print(Foo.a < Foo.b)
    print(Foo.b < 1)
    

一直尝试着做这件事,但我错过了第二步。谢谢! - Henny Lee
@Hamish 哦,好主意。这就是为什么我应该在发布之前编译的原因。让我试着调整一下 :) - Alexander
@Alexander 看起来不错 - 不过请注意,它将允许比较 Foo.a < Bar.a,其中 Bar 是使用 Int RawValueRawRepresentable,这可能是需要的,也可能不是。正如我在我的答案中所说的那样,在实践中,我并不完全相信添加这些类型的重载是一个好主意,因为我们可以只说 b.rawValue < 1 :) - Hamish
1
@Hamish 是的,我意识到了。说实话,我不会做任何这样的事情。我不喜欢这种隐式行为。而且,为所有 RawRepresentable 枚举定义比较是没有意义的。想象一下一个 Card 枚举。牌的排名完全取决于你玩的游戏。 - Alexander

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接