如何通过泛型获取数组结构 (SOA) 中的值?
How to get values in a struct-of-arrays (SOA) through a generic type?
我正在寻找您的 feedback/advice 一段代码。
基本上,我有这样一个 SOA:
struct Entities {
pub meshes: FakeArena<Mesh>,
pub lights: FakeArena<Light>,
}
我可以通过他的“句柄”访问特定的值(每个句柄都绑定到特定的类型),所以我可以通过 entities.meshes.get(&handle)
来获取网格的值。
到目前为止一切顺利,但我正在尝试通过相应的竞技场动态检索值来实现这一点。通过执行 entities.get(&handle)
如果句柄类型是 Mesh
,我 return entities.meshes.get(&handle)
。我的 Entities
结构有一个名为 get
:
的方法
fn get<T: Any>(&self, handle: &Handle<T>) -> &T {
let mut entity: Option<&dyn Any> = None;
let any = handle as &dyn Any;
any.downcast_ref::<Handle<Mesh>>()
.map(|handle| entity = Some(self.meshes.get(handle) as &dyn Any));
any.downcast_ref::<Handle<Light>>()
.map(|handle| entity = Some(self.lights.get(handle) as &dyn Any));
if entity.is_none() {
panic!("Type not found in stored entites.");
}
entity
.unwrap()
.downcast_ref::<T>()
.expect("Error while downcasting the entity type")
}
这非常有效。我将通用类型向下转换为具体类型,然后再次转换为通用类型,但这看起来很奇怪而且很棘手。
也许我遗漏了什么,或者您对此有更好的主意;你会怎么做? :)
这里不需要任何动态调度,普通的静态调度就足够了。
创建一个特征,它被赋予对容器结构的引用。每个组件类型都实现这个特征并选择容器的适当字段。然后,在你的 get
方法中要求特征并使用它:
struct Mesh;
struct Light;
struct Entities {
meshes: Vec<Mesh>,
lights: Vec<Light>,
}
trait Example {
fn get_in<'a>(&self, entities: &'a Entities) -> &'a Self;
}
impl Example for Mesh {
fn get_in<'a>(&self, entities: &'a Entities) -> &'a Self {
&entities.meshes[0]
}
}
impl Example for Light {
fn get_in<'a>(&self, entities: &'a Entities) -> &'a Self {
&entities.lights[0]
}
}
impl Entities {
fn get<T: Example>(&self, handle: T) -> &T {
handle.get_in(self)
}
}
fn example(entities: &Entities) {
let m = entities.get(Mesh);
let l = entities.get(Light);
}
我正在寻找您的 feedback/advice 一段代码。
基本上,我有这样一个 SOA:
struct Entities {
pub meshes: FakeArena<Mesh>,
pub lights: FakeArena<Light>,
}
我可以通过他的“句柄”访问特定的值(每个句柄都绑定到特定的类型),所以我可以通过 entities.meshes.get(&handle)
来获取网格的值。
到目前为止一切顺利,但我正在尝试通过相应的竞技场动态检索值来实现这一点。通过执行 entities.get(&handle)
如果句柄类型是 Mesh
,我 return entities.meshes.get(&handle)
。我的 Entities
结构有一个名为 get
:
fn get<T: Any>(&self, handle: &Handle<T>) -> &T {
let mut entity: Option<&dyn Any> = None;
let any = handle as &dyn Any;
any.downcast_ref::<Handle<Mesh>>()
.map(|handle| entity = Some(self.meshes.get(handle) as &dyn Any));
any.downcast_ref::<Handle<Light>>()
.map(|handle| entity = Some(self.lights.get(handle) as &dyn Any));
if entity.is_none() {
panic!("Type not found in stored entites.");
}
entity
.unwrap()
.downcast_ref::<T>()
.expect("Error while downcasting the entity type")
}
这非常有效。我将通用类型向下转换为具体类型,然后再次转换为通用类型,但这看起来很奇怪而且很棘手。
也许我遗漏了什么,或者您对此有更好的主意;你会怎么做? :)
这里不需要任何动态调度,普通的静态调度就足够了。
创建一个特征,它被赋予对容器结构的引用。每个组件类型都实现这个特征并选择容器的适当字段。然后,在你的 get
方法中要求特征并使用它:
struct Mesh;
struct Light;
struct Entities {
meshes: Vec<Mesh>,
lights: Vec<Light>,
}
trait Example {
fn get_in<'a>(&self, entities: &'a Entities) -> &'a Self;
}
impl Example for Mesh {
fn get_in<'a>(&self, entities: &'a Entities) -> &'a Self {
&entities.meshes[0]
}
}
impl Example for Light {
fn get_in<'a>(&self, entities: &'a Entities) -> &'a Self {
&entities.lights[0]
}
}
impl Entities {
fn get<T: Example>(&self, handle: T) -> &T {
handle.get_in(self)
}
}
fn example(entities: &Entities) {
let m = entities.get(Mesh);
let l = entities.get(Light);
}