I have an enum storing variant numeric types, lets say
enum MyNum {
Int(u8),
BigInt(u64),
Float(f64),
}
(I have even more variants in my actual code). Then I want to implement PartialOrd
for this enum, the only way I can think of is to enumerate all the cases manually:
impl PartialOrd for MyNum {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match (self, other) {
(MyNum::Int(l), MyNum::Int(r)) => l.partial_cmp(r),
(MyNum::Int(l), MyNum::BigInt(r)) => (*l as u64).partial_cmp(r),
(MyNum::Int(l), MyNum::Float(r)) => (*l as f64).partial_cmp(r),
(MyNum::BigInt(l), MyNum::Int(r)) => l.partial_cmp(&(*r as u64)),
(MyNum::BigInt(l), MyNum::BigInt(r)) => l.partial_cmp(r),
(MyNum::BigInt(l), MyNum::Float(r)) => (*l as f64).partial_cmp(r),
(MyNum::Float(l), MyNum::Int(r)) => l.partial_cmp(&(*r as f64)),
(MyNum::Float(l), MyNum::BigInt(r)) => l.partial_cmp(&(*r as f64)),
(MyNum::Float(l), MyNum::Float(r)) => l.partial_cmp(r)
}
}
}
Is there any easier and simpler approach to implement this? I have two possible solutions in mind, but not sure if they are feasible in rust.
The first one is to somehow allow pattern matching with same variant
match (self, other) {
(MyNum::_(l), MyNum::_(r)) => l.partial_cmp(r),
(MyNum::Int(l), MyNum::BigInt(r)) => (*l as u64).partial_cmp(r),
(MyNum::Int(l), MyNum::Float(r)) => (*l as f64).partial_cmp(r),
(MyNum::BigInt(l), MyNum::Int(r)) => l.partial_cmp(&(*r as u64)),
(MyNum::BigInt(l), MyNum::Float(r)) => (*l as f64).partial_cmp(r),
(MyNum::Float(l), MyNum::Int(r)) => l.partial_cmp(&(*r as f64)),
(MyNum::Float(l), MyNum::BigInt(r)) => l.partial_cmp(&(*r as f64)),
}
This solution saves 3 branches and it's more generalizable, and it's related to this post. The second one is somehow let a macro or function iterates all the variants
enumerate!(self, other, |l, r| (*l as f64).partial_cmp(&(*r as f64)))
I guess these two solutions could be accomplished using macros, but I'm not that experienced with macros. If there are some less-known syntax or crates that could be used, please let me know! Thank you!