【发布时间】:2018-01-18 18:25:20
【问题描述】:
我正在尝试在 Rust 中实现一个基本的ECS。我想要一个数据结构,为每个组件存储该特定组件的存储。因为有些组件很常见,有些却很少见,所以我想要不同类型的存储策略,例如VecStorage<T> 和HashMapStorage<T>。
由于游戏引擎的 ECS 不知道组件,我想出了:
trait AnyStorage: Debug {
fn new() -> Self
where
Self: Sized;
}
#[derive(Default, Debug)]
struct StorageMgr {
storages: HashMap<TypeId, Box<AnyStorage>>,
}
使用 VecStorage 和 HashMapStorage<T> 实现 AnyStorage 特征。由于AnyStorage 不知道T,我添加了两个具体存储实现的另一个特征:ComponentStorage<T>。
虽然我能够注册新组件(即在StorageMgr 的storages 中添加新的Box<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>>();
}
我知道我的问题来自storage的类型是&mut Box<AnyStorage>;我可以从中获取具体的VecStorage 吗?
做这一切的重点是我希望组件在内存中是连续的,并且为每种组件类型提供不同的存储空间。我无法解决自己使用Box<Component>,或者我不知道如何使用。
我将我的问题简化为最少的代码on Rust Playground。
【问题讨论】:
-
请edit 解释为什么它不是How do I create a heterogeneous collection of objects? 的重复项。
-
@Shepmaster 因为“通用”这个词。我知道如何创建异构集合以及如何在 Rust 中使用多态性,但不知道通用性。我应该将此添加为介绍性段落吗?
-
@totorigolo 那是不可能的。 Trait 对象不能有泛型类型参数,因为这些是在编译时解析的。解决这个问题的常用方法是通过所有组件的另一个共同特征来使用/操作包含的对象。或者忘记异质性并使用具体类型(例如,每种类型有多个容器,或者组件使用枚举类型)。
-
@E_net4 感谢您的澄清。但我意识到我的问题的标题非常不清楚。我想要做的不是stricto sensus 异构泛型的集合:从宏观角度来看,这就是
StorageMgr。 (我不能说清楚,抱歉)我写了一个共同特征,AnyStorage,正如你所建议的那样,我确信有办法让我的VecStorage回来,因为println!("{:?}", storage);打印VecStorage([])。 -
您只能这样做,因为您将
Debug约束添加到AnyStorage。听起来您想在AnyStorage中使用insert方法。
标签: rust