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

Rust Deref vs Implementing Iterators over inner types

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

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

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

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

然后我看到我可以实现 DerefDerefMut 并使用 deref 强制免费获得所有这些功能:

果然,这样做之后:

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 转换为通用类型,我会遇到问题吗?

如果这是个坏主意,有没有一种简单的方法可以将内部向量项的所有 iteration/map 功能放到封闭结构中?

此外,这是否有任何性能方面的考虑?

Deref 很好,因为你的结构特别是一个具有额外不变量的 vec(因此使其可用 as vec 似乎是明智的)但 DerefMut 似乎就像一个相当糟糕的主意,因为它会让调用者泄漏内部 Vec (作为可变引用)并破坏你的不变量。

一个选项可能是 Deref 到一个切片(而不是 vec),在这种情况下 DerefMut 也会给你一个切片,它有相当严格的限制,因此不会能够打破你的不变量。这将意味着您可能需要重新实现固有的 Vec 方法,并且无法冒充 Vec

另一种选择是根本不实现 DerefMut,并为它们提供更明确的方法。还有 WRT 迭代器,请注意,您只需要实现 IntoIterator 和其他迭代器生成方法(.iter().iter_mut()):结果可以是底层集合 [=40= 的任何迭代器].

现在我不知道你的意思

However, I was not sure which traits I should implement: are Iterator [...] enough?

在任何情况下,您都不应该直接在您的 SizedVec 上实施 Iterator。这是一个非常糟糕的想法。

迭代器子特征基本上是标记,它们提供了 Iterator 的附加功能(但不一定由每个 Iterator 类型实现)。如果您正确地委托您的迭代,底层迭代器类型可能已经实现了那些可能的。