Match on pair of enum when both are of the same kind
Solution 1:
I'm not sure how many of these operations you want to implement, and how many enum variants you actually have. Depending on that, the best answer changes quite a bit, I think. If you really only have one operation (interpolate
), and three variants: type it out, anything else will be a lot less simple and maintainable.
That being said, I might use
let geometry = binop!(match (&self.geometry, &other.geometry) {
(a, b) => *a.interpolate(b, t)
});
based on
macro_rules! binop {
(match ($av:expr, $bv:expr) { ($a:ident, $b:ident) => $op:expr }) => {{
use Geometry::*;
binop!($av, $bv, $a, $b, $op, Point, Curve, EPBox)
}};
($av:expr, $bv:expr, $a:ident, $b:ident, $op:expr, $($var:path),*) => {
match ($av, $bv) {
$(($var($a), $var($b)) => $var($op),)*
_ => unimplemented!("Kinds not matching")
}
};
}
Playground
You'll have to list up the enum variants once. If you don't want that, you'll have to go for a proc macro. I think that would be overkill.
Solution 2:
With your current code, you can't really do this. Checking if the enum variants are the same variant is fairly simple with the use of core::mem::discriminant
, but you can't access the contained value without match
or if let
statements. What you can do is use type parameters for the variables and type IDs. This is a really tacky way to do things, and should be avoided really, but it works. I've given an example to show you how you could implement it
use std::any::Any;
trait SomeTrait {
fn some_function(&self, other: Self) -> &Self;
}
#[derive(Clone)]
struct Var0 {
eg: i64
}
#[derive(Clone)]
struct Var1 {
other_eg: f64
}
fn check<T: 'static, B: 'static>(lhs: T, rhs: B) -> Option<T> {
if lhs.type_id() == rhs.type_id() {
Some(lhs.some_function(rhs))
} else {
None
}
}
fn main() {
let a = Var0{ eg: 2 };
let b = Var0{ eg: 9 };
let c = Var1 { other_eg: -3f64 };
assert!(check(a.clone(), b).is_some());
assert!(check(a, c).is_none());
}
impl SomeTrait for Var0 { /* ... */ }
impl SomeTrait for Var1 { /* ... */ }
Please note though: as I said before this is messy and pretty hacky and not very nice to read. If I were writing this I would use the match
statement over this, but it's up to you what you do since this does require some reworking to implement. I'm also not sure if you can use different lifetimes for the check
function other than `static
which might be a problem.