问题
Similar questions have been asked many times before, but the closest I have come to my case is here.
I'm trying to achieve something like this(although the match part is completely wrong).
struct A {
a: i8,
b: u8,
}
struct B {
c: i16,
d: u16,
}
enum select {
type_a(A),
type_b(B),
}
impl select {
fn return_one<T>(&self) -> T {
match self {
type_a(a) => a,
type_b(b) => b,
}
}
}
As you can see, it has an extra caveat, where the values inside the enum can be either of two structs. Is there some generics magic that I'm overlooking? Maybe I should compare the types with std::mem::discriminant()? I would very much to avoid having 2 methods using Option<T>.
回答1:
I was able to craft something that does kind-of what you are asking for, but I would not recommend it.
pub struct A {
a: i8,
b: u8,
}
pub struct B {
c: i16,
d: u16,
}
enum Select {
TypeA(A),
TypeB(B),
}
trait FromSelect {
fn from_select(sel: Select) -> Self;
}
impl FromSelect for A {
fn from_select(select: Select) -> Self {
match select {
Select::TypeA(a) => a,
_ => panic!("Tried to select B from A")
}
}
}
impl FromSelect for B {
fn from_select(select: Select) -> Self {
match select {
Select::TypeB(b) => b,
_ => panic!("Tried to select A from B")
}
}
}
impl Select {
fn return_one<T: FromSelect>(self) -> T {
FromSelect::from_select(self)
}
}
fn main() {
let s: Select = Select::TypeA(A { a: 5, b: 5 });
let _aa = s.return_one::<A>();
let s2: Select = Select::TypeA(A { a: 7, b: 7 });
// This Panics
let _bb = s2.return_one::<B>();
}
Playground
I say "Kind Of" because I could not define a FromSelect trait that did not consume the Select enum, for reasons I do not entirely understand.
Also, you said you don't want two different methods - I was only partially able to achieve that. In this solution there are two methods defined, but the caller does not need to know that as they are abstracted over using generics.
As you can see from the main function, you need to use "turbofish" syntax to specify at compile time the variant you want to get back (or you could annotate the variable you are putting it into) - but if you get that wrong the program panics. Worse, the compiler will not be able to warn you that you have gotten it wrong!
To me that negates whatever slight benefit you might get. On top of that there is quite a lot of boiler plate required.
来源:https://stackoverflow.com/questions/61704402/dependending-on-what-variant-an-enum-is-how-to-return-one-of-2-different-possib