Generics in trait

Hello,

how can I make this compile? Is this even possible? I've created a gist here

The problem is type Storage, how to deal with T here? T can be either XState or YState here, but of course not limited to either of them, imagine ZState.

Thanks!

use std::collections::HashMap;

fn main() {
    let tmp = Library {
	    components: HashMap::new(),
    };
}

type Storage = HashMap<String, Box<dyn Component<T> + 'static + Send>>;

pub struct Library {
	components: HashMap<u64, Storage>,
}

pub trait Component<T> {
	fn get_state(&self) -> &T;
}

//X-Component
struct XState{}
struct XComponent{
    machine: Option<XState>,
}

impl Component<XState> for XComponent {
	fn get_state(&self) -> &XState
	{
		self.machine.as_ref().unwrap()
	}
}

//Y-Component
struct YState{}
struct YComponent{
    machine: Option<YState>,
}

impl Component<YState> for YComponent {
	fn get_state(&self) -> &YState
	{
		self.machine.as_ref().unwrap()
	}
}
type Storage<T> = ...;

You can use it like,

Storage<XState>

Thanks for your fast reply.

Yes, but this
Storage<XState>
does limit Storage to XState. So at the end of the day I'd have

pub struct Library {
	components: HashMap<u64, Storage<XState>>,
}

but this is not what I want. I want a generic Library which can store all XState and YStates. Is this possible?

Oh, I see, you can't do that without some sort of type erasure. typemap handles this well.

The reason this can't work is because you have a number of different types that you want to store in a HashMap, but the HashMap expexts the same type for all it's elements.

1 Like

Does this mean hashmap provided by std library can't have trait objects as values?

Is there any particular reason for choosing to use generics in the trait definition instead of the associated type?

In general, generic type is something the trait implementation receives, and associated type denote something that it provides. Take, for example, std::ops traits: they have both the generic type - the right side of the operation, which could be different, and the associated type - the result of the operation, entirely depending on the source types.

Yes, HashMap can't store trait objects directly. You can work around this by boxing trait objects.