I'm trying to use a trait object in a hashmap so I can call an update function.
This here is really the code I'm trying to write. I am pretty sure that I can change this code to get this to work the way that I want as-is, but I figured I can turn this into a learning opportunity because the Sized stuff is not quite clear to me.
let mut hm: HashMap<SomeEnum, Box<dyn SomeTrait>> = HashMap::new();
hm.entry(SomeEnum::Type1).and_modify(|b| b.some_other_func()).or_insert(/* HOW */ default());
But I don't really understand the Sized restrictions on trait objects or what Sized is (or why using Default as a Supertrait prevents the object from being Sized). If the entry does not exist in the hashmap, I would like to add the default version of that object to the entry.
Here's an reprex showing my issue.
use std::collections::HashMap;
#[derive(PartialEq, Eq, Hash)]
enum SomeEnum {
Type1,
Type2,
}
// SomeTrait is a subtrait of Default
// Because I want every type to implement Default
trait SomeTrait: Default {
fn new() -> Self {
Self {
..Default::default()
}
}
fn some_other_func(&self);
}
// SomeStruct implements Default and SomeTrait
struct SomeStruct {
foo: i32,
}
impl Default for SomeStruct {
fn default() -> Self {
SomeStruct { foo: 10 }
}
}
impl SomeTrait for SomeStruct {
fn some_other_func(&self) {}
}
fn main() {
let mut hm: HashMap<SomeEnum, Box<dyn SomeTrait>> = HashMap::new();
hm.entry(SomeEnum::Type1)
.and_modify(|b| b.some_other_func())
.or_insert(/* HOW */ default());
}
I cannot use a generic type instead of the trait object because I do/will have multiple implementations of this trait.
I have also tried creating a new trait that is a subtrait of both Default and the one I want:
trait AutoSomeType: SomeType + Default {}
trait SomeType {
fn new() -> Self
where
Self: Sized,
{
Self {
..Default::default()
}
}
fn some_other_func(&self);
}
I got here somehow based on a compiler recommendation, but I feel like this isn't on the right track to a solution.