如何解决Rust Deref 与在内部类型上实现迭代器
这是一个包含向量的玩具结构
struct SizedVec {
items: Vec<u32>,cap: usize,}
我想在 SizedVec
上有迭代函数,这样它们就可以像我直接迭代项目一样工作。
但是,我不确定应该实现哪些特征:Iterator
和 IntoIterator
是否足够? the docs 中有很多特征
而且它们看起来有点复杂和乏味。
然后我看到我可以实现 Deref
和 DerefMut
并使用 deref coercion 免费获得所有这些功能:
果然,做完之后:
impl Deref for SizedVec {
type Target = Vec<u32>;
fn deref(&self) -> &Self::Target {
&self.items
}
}
impl DerefMut for SizedVec {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.items
}
}
我可以使用我想要的所有迭代器。但是我想实现一个自定义的推送逻辑,但是 DeRef
已经给了我一个推送。但是根据文档我应该没问题,因为显然查找是按顺序为每种类型完成的
impl SizedVec {
fn from_size(size: usize) -> Self {
Self {
items: vec![],cap: size,}
}
fn push(&mut self,item: u32) {
if self.items.len() < self.cap {
self.items.push(item);
}else {
self.items.pop();
self.items.push(item);
}
}
}
这似乎有效,
fn main () {
let mut svec = SizedVec::from_size(2); // Custom function I implemented
svec.push(2);
svec.push(3);
svec.push(4);
svec.iter_mut().for_each(|item| {*item = *item + 2});
println!("{}",svec); // Items: [4,6],Cap: 2 (Implemented display so this works)
}
这一切似乎都很好,但我的问题是:这是个好主意吗?如果我将 SizedVec
转换为泛型类型,我会遇到问题吗?
如果这是一个坏主意,是否有一种简单的方法可以将内部向量项的所有迭代/映射功能放到封闭结构上?
另外,是否有任何性能方面的考虑?
解决方法
Deref
很好,因为您的结构特别是一个带有附加不变量的 vec(因此使其可用 as vec 似乎是明智的)但 DerefMut
似乎是一个相当糟糕的主意因为它会让调用者泄漏内部 Vec
(作为可变引用)并破坏你的不变量。
一种选择可能是 Deref
到切片(而不是 vec),在这种情况下 DerefMut
也会为您提供一个切片,该切片具有非常严格的限制,因此将无法打破你的不变量。这意味着您可能需要重新实现固有的 Vec
方法,但无法将其作为 Vec
进行传递。
另一种选择是根本不实现 DerefMut
,并为这些提供更明确的方法。同样是 WRT 可迭代对象,请注意,您只需要实现 IntoIterator
和其他迭代器生成方法(.iter()
、.iter_mut()
):结果可以是底层集合返回的任何迭代器。>
现在我不知道你说的是什么
但是,我不确定我应该实现哪些特征:Iterator [...] 足够了吗?
在任何情况下,您都不应直接在您的 Iterator
上实现 SizedVec
。这是一个可怕的、可怕的想法。
迭代器子特征基本上是标记,它们提供了超过 Iterator
的附加功能(但不一定由每个 Iterator
类型实现)。如果您正确委派迭代,则底层迭代器类型可能已经实现了那些可能的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。