I would like or call a trait method on a type if that type implements the trait, otherwise I would like to return an error or panic. If there is never an attempt to call the trait method, then there should be no error. I only want an error if there is an attempt to call it, but it doesn't exist.
I want to do something like this:
pub trait Foo {
fn foo(&self);
}
pub trait Bar {
fn bar(&self);
}
pub enum Command {
Foo,
Bar,
}
pub fn execute_command<T>(t: &T, command: Command) {
match command {
Command::Foo => {
/*
if T: Foo {
t.foo();
} else {
panic!("Type does not implement Foo");
}
*/
}
Command::Bar => {
/*
if T: Bar {
t.bar();
} else {
panic!("Type does not implement Bar");
}
*/
}
}
}
Using the above would look like this:
struct Struct;
impl Foo for Struct {
fn foo(&self) {
println!("Foo");
}
}
fn main() {
let s = Struct;
execute_command(&s, Command::Foo); // calm
execute_command(&s, Command::Bar); // panic
}
I can't seem to figure out how to do this with Rust generics. It's easy with C++ templates but what good does that do me! I thought that maybe I could write a version of execute_command
for each combination of Foo
and Bar
but that would require knowing which function to call (because you can't overload functions). That might depend on negative trait bounds too. It's also a little tedious because the real code has 4 traits so that would be 16 functions.
My first attempt was something like this:
fn as_foo<T: Foo>(t: &T) -> &impl Foo {
t
}
fn as_foo<T: !Foo>(t: &T) -> &impl Foo {
panic!("Type does not implement Foo")
}
That's not even close to working because it depends on negative trait bounds and overloading and there's no way to properly use it from execute_command
.
I'm stumped. I can't figure it out. Any ideas?