Henny Lee
Henny Lee

Reputation: 3052

Comparable Enum with Int

To compare enums which has an Int as the raw value I've added:

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

Now I can do:

enum Foo: Int {
    case a = 1
    case b = 2
}

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

print(a < b) // true

But how should I make it so I can compare enums like:

print(b < 1) // error

Upvotes: 4

Views: 1615

Answers (3)

Hamish
Hamish

Reputation: 80801

A slightly more generic version of @matt's solution – which would allow you to compare a given RawRepresentable with its RawValue. Although note that you'll have to implement both overloads for both < & > in order to allow for all 4 possible combinations of comparisons.

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

Although that being said, I would be wary of using such overloads. It's not so bad being able to say such things as b < 1, but the waters get more murky when allowing you to say b < c where c is an Int – it begins to become slightly unclear what you're actually comparing (not to mention adding extra complexity to overload resolution).

Simply saying print(b.rawValue < 1) is both clear and concise, and is the way I'd write it.

Upvotes: 2

Alexander
Alexander

Reputation: 63177

Int isn't RawRepresentable, so it can't be used with your < operator.

Here are two fixes:

  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)
    

Upvotes: 1

matt
matt

Reputation: 535057

You would just do more of what you're already doing:

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

Upvotes: 2

Related Questions