Reputation: 15529
I am trying to use something equivalent to the following code:
struct MyStruct {}
struct MyStruct2 {}
trait CanDoIt {
fn do_it(&self) -> String;
}
impl CanDoIt for MyStruct {
fn do_it(&self) -> String {
"done".into()
}
}
impl CanDoIt for MyStruct2 {
fn do_it(&self) -> String {
"done 2".into()
}
}
fn do_a<T: CanDoIt>(value: T) -> String {
value.do_it()
}
fn main() {
let s: dyn CanDoIt = if true {
MyStruct {}
} else {
MyStruct2 {}
};
println!("Done it: {}", do_a(s))
}
The if condition could be dependent on some runtime value, for example whether the hardware supports some feature.
I tried different things, like making the struct also implement Sized
, but I always get some compile error like this:
|
29 | let s: dyn CanDoIt = if true {
| ^ doesn't have a size known at compile-time
|
What is the solution for when you need to pass around different implementations depending on some runtime value?
Upvotes: 0
Views: 61
Reputation: 1803
Traits like your CanDoIt
are non sized, because they are not a concrete type and thus can't be stored as values directly. One can only store a trait object like Box<dyn CanDoIt>
or &dyn CanDoIt
So for your example using &dyn CanDoIt
it would look like this:
struct MyStruct {}
struct MyStruct2 {}
trait CanDoIt {
fn do_it(&self) -> String;
}
impl CanDoIt for MyStruct {
fn do_it(&self) -> String {
"done".into()
}
}
impl CanDoIt for MyStruct2 {
fn do_it(&self) -> String {
"done 2".into()
}
}
fn do_a(value: &dyn CanDoIt) -> String {
value.do_it()
}
fn main() {
let s: &dyn CanDoIt = if true {
&MyStruct {}
} else {
&MyStruct2 {}
};
println!("Done it: {}", do_a(s))
}
Upvotes: 1