Rust如何在trait中返回另一trait的迭代器并支持find操作
问题根源与解决方案
第一个错误(NodeLike不能转为trait对象)的原因
你为NodeLike trait 添加了 : Sized 超类约束,而Rust明确规定:带有Sized超约束的trait不满足对象安全要求,这和trait内部的方法定义无关,直接去掉该约束即可解决第一个编译错误。
第二个错误(无法在迭代器上调用find方法)的原因
你在iter_source_nodes方法的返回值、迭代器Item类型中直接使用了dyn Trait类型:
dyn Trait是动态大小类型,无法直接作为函数返回值、函数参数、集合元素等要求固定大小的场景使用- 未用指针包装的
dyn Iterator本身没有实现Iteratortrait,自然无法调用find等迭代器方法
最终修改方案
最通用的实现方式是用Box智能指针包装所有动态大小的trait对象,修改后的完整代码如下:
pub trait NodeLike { /// Get the node id fn get_id(&self) -> i32; } pub trait EdgeLike { /// Get the destination node id fn get_node_id(&self) -> i32; /// Get the edge id fn get_edge_id(&self) -> i32; /// iterates of the source nodes /// + '_ 生命周期标注表示迭代器的生命周期与当前EdgeLike实例绑定 fn iter_source_nodes(&self) -> Box<dyn Iterator<Item = Box<dyn NodeLike>> + '_>; } fn operation(id: i32, edge: &dyn EdgeLike) { // Box<dyn Iterator> 本身实现了Iterator trait,可以正常调用find方法 if let Some(node) = edge.iter_source_nodes().find(|n| n.get_id() == id) { // 此处编写对应节点的处理逻辑 } }
可选优化(减少堆分配)
如果所有NodeLike实例的生命周期都和对应EdgeLike实例绑定,你可以用引用代替Box<dyn NodeLike>进一步减少堆分配:
pub trait EdgeLike { // 其他方法不变 fn iter_source_nodes(&self) -> Box<dyn Iterator<Item = &dyn NodeLike> + '_>; }
内容的提问来源于stack exchange,提问作者l3utterfly
相关产品推荐
相关产品推荐

