Reputation: 2235
I would like to pass in the parameters what arm of the enum I need to match, something like this:
enum D {
A(i64),
B(u64),
C(u64, u64),
}
let a = D.A(10);
println!(a.is_of(D.A)); // true
println!(a.is_of(D.B)); // false
I know I can use matching rules for this, but I'd like this is_of
method to take as an input of the enum options for my purposes.
Upvotes: 12
Views: 15253
Reputation: 11
It's possible to create an is_of
function like you suggest, but with some caveats, and I don't recommend it.
In general, you can indeed pass enum variants as function parameters. While enum variants are not types, they are functions, and you can pass functions as parameters all you want. The problem is making an is_of
function that can take any of your variants as an argument.
If all of your variants took the same type, you could do this:
#[derive(Clone, Copy, PartialEq)]
enum Foo {
A(u64),
B(u64),
C(u64),
}
impl Foo {
fn into_inner(self) -> u64 {
match self {
Foo::A(n) | Foo::B(n) | Foo::C(n) => n
}
}
fn is_of(self, variant: fn(u64) -> Foo) -> bool {
self == variant(self.into_inner())
}
}
fn main() {
assert!(Foo::A(10).is_of(Foo::A))
}
Importantly, is_of
will take any function pointer that returns Foo
, so you can pass in arbitrary functions with the correct signature in addition to the variants.
Alternatively, if all your variants are different types (as in your case), you can define a trait that will allow you to pass the different variants in.
enum Bar {
A(u64),
B(u32, i32),
}
impl Bar {
fn is_of<V: Variant<Args>, Args>(self, variant: V) -> bool {
V::check(self)
}
}
trait Variant<Args> {
fn check(this: Bar) -> bool;
}
impl<F: Fn(u64) -> Bar> Variant<(u64,)> for F {
fn check(this: Bar) -> bool {
matches!(this, Bar::A(_))
}
}
impl<F: Fn(u32, i32) -> Bar> Variant<(u32, i32)> for F {
fn check(this: Bar) -> bool {
matches!(this, Bar::B(_, _))
}
}
Obviously, this code is not really doing anything useful, and it opens you up to all sorts of bugs. If you were gonna do something like this, you would probably want to generate the trait definitions with a macro at least. And it has the same caveat as above that it'll accept any functions with matching signatures, not just the variants.
Upvotes: 1
Reputation: 658057
The discriminant of an enum variant can be passed for compairson
use std::mem::{discriminant,Discriminant};
enum MyEnum {
A,
B,
}
fn is_enum_variant(value: &MyEnum, d: Discriminant<MyEnum>) -> bool {
discriminant(value) == d
}
fn main() {
println!("Is variant: {}", is_enum_variant(&MyEnum::A, discriminant(&MyEnum::A)));
println!("Is variant: {}", is_enum_variant(&MyEnum::A, discriminant(&MyEnum::B)));
}
Upvotes: 4
Reputation: 432009
You cannot.
If you are OK using a macro instead of a function, see
See also:
Upvotes: 17