简体   繁体   English

如何为具有底层集合的结构实现非消耗 IntoIterator?

[英]How do I implement a non-consuming IntoIterator for a struct with an underlying collection?

Let's say I have a struct that has a collection, such as a Vec as one of its data members:假设我有一个具有集合的struct ,例如Vec作为其数据成员之一:

struct MyCollection {
    data: Vec<i32>
}

I want the user of MyCollection to be able to iterate over its data without direct access to the Vec itself, like so:我希望MyCollection的用户能够在不直接访问Vec本身的情况下迭代其数据,如下所示:

let x = MyCollection{data:vec![1, 2, 3, 4, 5]};

for i in &x {
    //...
}

However, I'm struggling with implementing the necessary Trait IntoIterator for the non-consuming version with &x .但是,我正在努力使用&x为非消费版本实现必要的 Trait IntoIterator I have successfully implemented the consuming version:我已经成功实现了消费版本:

impl std::iter::IntoIterator for MyCollection {
    type Item = i32;
    type IntoIter = std::vec::IntoIter<Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        return self.data.into_iter();
    }
}

However, this is only usable as follows:但是,这仅适用于以下情况:

for i in x {
    println!("{:?}", i);
}

which consumes x .消耗x Cloning the data is possible, but quite expensive, so I'd like to avoid that.克隆数据是可能的,但非常昂贵,所以我想避免这种情况。

Here is what I have so far for the non-consuming version, which I based on the source implementation of std::vec::Vec :到目前为止,这是我基于std::vec::Vec源实现的非消费版本的内容:

impl<'a> std::iter::IntoIterator for &'a MyCollection {
    type Item = &'a i32;
    type IntoIter = std::vec::IntoIter<Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        return self.data.into_iter();
    }
}

which produces the following compile error:这会产生以下编译错误:

error: mismatched types
error: expected &i32, found i32
note: expected type `std::vec::IntoIter<&i32>`
   found type `std::vec::IntoIter<i32>`
error: expected `std::vec::IntoIter<&i32>` because of return type

I have also tried removing the &'a of the type Item since in my case, the elements of data are Copy able, but this yields the following:我还尝试删除type Item&'a ,因为在我的情况下, data元素是可Copy ,但这会产生以下结果:

error: cannot move out of `self.data` which is behind a shared reference
error: move occurs because `self.data` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait

I understand the function wants an IntoIter of a vector to references, but I'm unsure how to give it one efficiently.我知道该函数需要一个向量的IntoIter来引用,但我不确定如何有效地给它一个。 I'm new to Rust, so I'd much appreciate some clarity on the concern.我是 Rust 的新手,所以我非常感谢您对这个问题的一些澄清。 Bonus points if you can also tell me how to create a mutable iterator for write access in the same fashion.如果您还可以告诉我如何以相同的方式创建用于写访问的可变迭代器,则可以加分。

First, you should use slice type, your user shouldn't have to know that you inner type is vector.首先,您应该使用切片类型,您的用户不必知道您的内部类型是向量。 Then, your problem is that you must not use IntoIter type, but Iter type directly.那么,你的问题是你不能使用IntoIter类型,而是直接使用Iter类型。

Simple example:简单的例子:

struct MyCollection {
    data: Vec<i32>,
}

impl<'a> std::iter::IntoIterator for &'a MyCollection {
    type Item = <std::slice::Iter<'a, i32> as Iterator>::Item;
    type IntoIter = std::slice::Iter<'a, i32>;

    fn into_iter(self) -> Self::IntoIter {
        self.data.as_slice().into_iter()
    }
}

fn main() {
    let x = MyCollection {
        data: vec![1, 2, 3, 4, 5],
    };

    for i in &x {
        println!("{}", i);
    }
}

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

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