下面是我制作的一个小程序示例:

type Index = usize;
type ValType = u32;

#[derive(Debug)]
pub struct NewVec(pub Vec<ValType>);

impl IntoIterator for NewVec {
    type Item = (Index, ValType);
    type IntoIter = <Vec<(Index, ValType)> as IntoIterator>::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        self.0
            .into_iter()
            .enumerate()
            .collect::<Vec<_>>()
            .into_iter()
    }
}

fn main() {
    let v = vec![100];
    let new_v = NewVec(v.clone());
    
    println!("Vec::into_iter:    {:?}", v.into_iter());
    println!("NewVec::into_iter: {:?}", new_v.into_iter());
    
}

此程序正确运行,并生成以下输出:

Vec::into_iter:    IntoIter([100])
NewVec::into_iter: IntoIter([(0, 100)])

然而,NewVec::into_iterator调用collect()来创建一个新的Vec,然后调用它的into_iter().

我的目标是消除对collect()的调用,直接返回一个迭代器. 我希望避免不必要的分配.

这个是可能的吗?你会怎么做呢?

请注意,如果我们删除对.Collect()的调用,则会收到以下错误:

error[E0308]: mismatched types
  --> src/main.rs:12:9
   |
11 |       fn into_iter(self) -> Self::IntoIter {
   |                             -------------- expected `std::vec::IntoIter<(usize, u32)>` because of return type
12 | /         self.0
13 | |             .into_iter()
14 | |             .enumerate()
15 | |             .into_iter()
   | |________________________^ expected `IntoIter<(usize, u32)>`, found `Enumerate<IntoIter<u32>>`
   |
   = note: expected struct `std::vec::IntoIter<(usize, u32)>`
              found struct `Enumerate<std::vec::IntoIter<u32>>`

但我不知道如何将Enumerate变成std::vec::IntoIter,或者这是否可能.

playground

推荐答案

因为.enumerate()提供了迭代器,所以我将直接返回它. 我们只需调整Self::IntoIter以匹配准确的类型(编译器的错误消息对我们有很大帮助).

impl IntoIterator for NewVec {
    type Item = (Index, ValType);
    type IntoIter = std::iter::Enumerate<std::vec::IntoIter<ValType>>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter().enumerate()
    }
}

以下是 comments 中的建议,带有拳击+动态调度.

impl IntoIterator for NewVec {
    type Item = (Index, ValType);
    type IntoIter = Box<dyn Iterator<Item = Self::Item>>;

    fn into_iter(self) -> Self::IntoIter {
        Box::new(self.0.into_iter().enumerate())
    }
}

...

for e in new_v.into_iter() {
    println!("{:?}", e);
}

Rust相关问答推荐

rust 蚀将动力特性浇到混凝土 struct 上是行不通的

为什么`Vec i64`的和不知道是`Option i64`?

使用Box优化可选的已知长度数组的内存分配

如何go 除多余的(0..)在迭代中,当它不被使用时?

如何在不调用Collect()的情况下为新型vec实现IntoIterator?

不能在Rust中使用OpenGL绘制三角形

在macro_rule中拆分模块和函数名

使用 select 处理 SIGINT 和子等待!无阻塞

UnsafeCell:它如何通知 rustc Select 退出基于别名的优化?

带引脚和不带引脚的比较功能

从字节数组转换为字节元组和字节数组时,为什么 Transmute 会对字节重新排序?

仅发布工作区的二进制 crate

Rust中的一生语法有什么作用?

部署Rust发布二进制文件的先决条件

trait 对象指针的生命周期

没有明确地说return会产生错误:match arms have incompatible types

Rust 函数指针似乎被borrow 判断器视为有状态的

预期类型参数,发现不透明类型

如何为返回正确类型的枚举实现 get 方法?

为什么 Bevy 的 Trait 边界不满足 Rapier 物理插件?