在Rust中存储具有泛型类型参数的异构类型集合

在Rust中存储具有泛型类型参数的异构类型集合,rust,Rust,我正在尝试在Rust中实现一个基本功能。我想要一个数据结构,为每个组件存储一个特定组件的存储器。由于某些组件是通用的,而其他组件是稀有的,因此我需要不同类型的存储策略,例如VecStorage和HashMapStorage 由于游戏引擎的ECS不知道组件,我想到了: trait AnyStorage: Debug { fn new() -> Self where Self: Sized; } #[derive(Default, Debug)] struct

我正在尝试在Rust中实现一个基本功能。我想要一个数据结构,为每个组件存储一个特定组件的存储器。由于某些组件是通用的,而其他组件是稀有的,因此我需要不同类型的存储策略,例如
VecStorage
HashMapStorage

由于游戏引擎的ECS不知道组件,我想到了:

trait AnyStorage: Debug {
    fn new() -> Self
    where
        Self: Sized;
}

#[derive(Default, Debug)]
struct StorageMgr {
    storages: HashMap<TypeId, Box<AnyStorage>>,
}

我知道我的问题来自这样一个事实,
存储
的类型是
&mut-Box。

我不确定这样的事情是否可能发生,但我终于找到了答案。关于您发布的示例失败的原因,有几点需要注意

  • Trait
    AnyStorage
    在您的示例中没有实现
    ComponentStorage
    ,因此,因为您将“存储”存储在
    哈希映射中
    哪里
    自我:大小;
    fn插入(&mut self,值:T);
    }
    结构存储管理器{
    存储:HashMap,
    }
    impl-StorageMgr{
    pub fn new()->Self{
    自我{
    存储:HashMap::new(),
    }
    }
    pub fn get_storage_mut(&mut self)->&mut::storage{
    让type_id=TypeId::of::();
    //如果存储尚不存在,请添加存储
    if!self.storages.包含\u键(&键入\u id){
    让新存储=::存储::新();
    self.storages.insert(type_id,Box::new(new_storage));
    }
    //获取此类型的存储空间
    匹配self.storages.get_mut(&type_id){
    一些(可能是_存储)=>{
    //将Any转换为该类型的存储
    可能与存储匹配。向下播放\u mut::(){
    一些(存储)=>存储,
    None=>unreachable!(),//unreachable!(),
    }
    }
    }
    
    请您的问题解释为什么它不是的副本。@Shepmaster,因为“generic”这个词。我知道如何创建异构集合以及如何在Rust中使用多态性,但不知道如何使用泛型。我是否应该将此作为介绍性段落添加?@ToToTorigolo这是不可能的。Trait对象不能具有泛型类型参数,因为这些参数是在编译时解析的。通常的解决方法是使用/操作c通过所有组件的另一个共同特征来定义对象。即,忽略异构性并使用具体类型(例如,每个类型有多个容器,或者组件有一个枚举类型)@E_net4谢谢你的澄清。但我意识到我问题的标题很不清楚。我想做的不是严格意义上的异构泛型集合:这就是从宏观角度看的
    StorageMgr
    。(对不起,我说不清楚)我写了一个共同的特点,
    AnyStorage
    ,正如您所建议的,我确信有一种方法可以让我的
    VecStorage
    返回,因为
    println!(“{:?}”,storage);
    打印
    VecStorage([])
    。只能这样做,因为您将
    Debug
    约束添加到了
    AnyStorage
    。听起来您希望在
    AnyStorage
    中插入
    方法。
    
    pub fn add_component_to_storage<C: Component>(&mut self, component: C) {
        let storage = self.storages.get_mut(&TypeId::of::<C>()).unwrap();
        // storage is of type: &mut Box<AnyStorage + 'static>
    
        println!("{:?}", storage); // Prints "VecStorage([])"
    
        storage.insert(component); // This doesn't work
    
        // This neither:
        // let any_stor: &mut Any = storage;
        // let storage = any_stor.downcast_ref::<ComponentStorage<C>>();
    }
    
    trait Component: Debug + Sized + Any {
        type Storage: Storage<Self>;
    }
    
    trait Storage<T: Debug>: Debug + Any {
        fn new() -> Self
        where
            Self: Sized;
    
        fn insert(&mut self, value: T);
    }
    
    struct StorageMgr {
        storages: HashMap<TypeId, Box<Any>>,
    }
    
    impl StorageMgr {
        pub fn new() -> Self {
            Self {
                storages: HashMap::new(),
            }
        }
    
        pub fn get_storage_mut<C: Component>(&mut self) -> &mut <C as Component>::Storage {
            let type_id = TypeId::of::<C>();
    
            // Add a storage if it doesn't exist yet
            if !self.storages.contains_key(&type_id) {
                let new_storage = <C as Component>::Storage::new();
    
                self.storages.insert(type_id, Box::new(new_storage));
            }
    
            // Get the storage for this type
            match self.storages.get_mut(&type_id) {
                Some(probably_storage) => {
                    // Turn the Any into the storage for that type
                    match probably_storage.downcast_mut::<<C as Component>::Storage>() {
                        Some(storage) => storage,
                        None => unreachable!(), // <- you may want to do something less explosive here
                    }
                }
                None => unreachable!(),
            }
        }
    }