繁体   English   中英

在另一个特征上添加一个特征的迭代器

[英]Adding an iterator of a trait on another trait

我有一个特征,它有一个函数应该返回一个不同特征的迭代器。 我还需要一个通用函数,它接受这个特征并对其进行操作。

这是我当前的代码:

pub trait NodeLike : Sized {
    /// 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
    fn iter_source_nodes(&self) -> dyn Iterator<Item = dyn NodeLike>;
                                                       ^^^^^^^^^^^^^
}

fn operation(id: i32, edge: dyn EdgeLike) {
    for node in edge.iter_source_nodes().find(|n| n.get_id() == id) {
        
    }
}

上面带下划线的部分会引发编译器错误:

the trait `NodeLike` cannot be made into an object
`NodeLike` cannot be made into an object rustc E0038
main.rs(1, 22): for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

NodeLike文档,我相信我的NodeLike特性是对象安全的。 它唯一的功能是&Self (ie &self)

现在,我可以通过删除NodeLike上的Sized特征来进一步我的代码。 但是,然后在函数operation出现错误; 我无法在迭代器上使用find函数。

如何更改我的代码以便我可以使NodeLike对象安全,并且能够返回一个迭代器,我可以在其上调用find

按照 Stargateur 的建议和你的游乐场链接,我得到了这样的编译:

游乐场链接

这是如果您不想使用任何不稳定的功能。

诀窍是指定迭代器的显式类型。 如果您不知道该类型,只需放入任何愚蠢的类型并让编译器抱怨类型不匹配。 它会告诉你我们在这里处理的是切片迭代器,因此是std::slice::Iter

其他修改是关于向结构添加生命周期参数,因为iter()返回引用。 如果您不希望那样,请将其更改为into_iter ,但是您必须使用self而不是&self

还有,为了你的手术,你必须做一些终生的魔法……

fn operation<'a, Item: NodeLike>(id: i32, edge: &'a impl EdgeLike<'a, Item=Item> )

如果您对不稳定的功能没问题,则可以避免指定迭代器的确切类型:在您的操场版本中,只需将dyn更改为impl 编译器会告诉您这是一个不稳定的功能,并会向您显示要使用的宏。

最后,为了避免必须向 trait 本身添加生命周期注释,有一些关于泛型关联类型的东西,但现在也许这太过分了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM