微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Rust Deref 与在内部类型上实现迭代器

如何解决Rust Deref 与在内部类型上实现迭代器

这是一个包含向量的玩具结构

struct SizedVec {
    items: Vec<u32>,cap: usize,}

我想在 SizedVec 上有迭代函数,这样它们就可以像我直接迭代项目一样工作。

但是,我不确定应该实现哪些特征:IteratorIntoIterator 是否足够? the docs 中有很多特征 而且它们看起来有点复杂和乏味。

然后我看到我可以实现 DerefDerefMut 并使用 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 举报,一经查实,本站将立刻删除。