Rust中如何编写接受标记组件作为类型参数的泛型函数
问题原因
你遇到的编译错误本质是两个问题:
- 未显式导入
specs::Jointrait:Specs的join方法是定义在Jointrait上的,没有导入该 trait 时无法调用 - 泛型约束和生命周期标注缺失:
ReadStorage、WriteStorage、Entities都和ECS World的生命周期绑定,且参与join的三个类型需要满足Jointrait约束
解决方案
不需要自定义任何trait,补全生命周期和泛型约束即可实现预期的泛型函数:
首先确认你已经导入了必要的依赖:
use specs::{Component, Entities, Join, ReadStorage, WriteStorage}; use std::collections::HashMap; use specs::world::Index;
然后编写泛型函数:
fn collect_position_map<'a, T>( entities: &'a Entities<'a>, storable: &'a ReadStorage<'a, T>, positions: &'a WriteStorage<'a, Position>, ) -> HashMap<(u8, u8), Index> where T: Component, // 约束三个参数的组合可以执行join操作,返回的元素类型符合预期 (&'a Entities<'a>, &'a ReadStorage<'a, T>, &'a WriteStorage<'a, Position>): Join<Item = (specs::Entity, &'a T, &'a Position)>, { (entities, storable, positions) .join() .map(|(ent, _, pos)| ((pos.x, pos.y), ent.id())) .collect() }
调用时直接传入对应存储实例即可:
let mov = collect_position_map(&entities, &movables, &positions); let immov = collect_position_map(&entities, &immovables, &positions);
复杂度评估
这个重构没有额外运行时开销:Rust的泛型会在编译期单态化,生成的代码和你手写两份逻辑完全一致,执行效率没有任何损失。同时你只需要维护一份逻辑,后续修改收集规则时不需要重复修改多处,收益远大于极小的代码编写成本。
内容的提问来源于stack exchange,提问作者Brian Kessler
相关产品推荐
相关产品推荐

