I want to have a function foo
taking an instance of a type which implements a trait A
. I always prefer to use generics in order to have static dispatch:
trait A {}
fn foo<T: A>(t: T) {}
However, this approach introduces some inflexibility, I can't pass a trait object like here:
trait A {}
fn foo(t: &A) {}
The thing is, sometimes I know the type and sometimes not. Is there a way to have both dynamic dispatch for trait objects and static dispatch for compile time known types while not implementing things twice?
That is indeed possible. One option is to explicitly implement A
for its reference types:
impl<'a, T: A + ?Sized> A for &'a T {}
The argument becomes a trait object when T = &A
, while still doing static dispatch for known implementors of A
. The following code should now compile:
fn foo<T: A>(a: T) {}
struct MyA;
impl A for MyA {}
fn main() {
foo(MyA{});
foo(&MyA{});
foo(&MyA{} as &A);
}
If you are willing to always pass a borrowed argument, you can also do this instead:
fn foo<T: A + ?Sized>(a: &T) {}
The argument becomes a trait object when T = A
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With