我在迭代器上应用闭包,我想使用stable,所以我想返回一个装箱的Iterator.显而易见的方法是:

struct Foo;

fn into_iterator(myvec: &Vec<Foo>) -> Box<dyn Iterator<Item = &Foo>> {
    Box::new(myvec.iter())
}

这会失败,因为借阅判断器无法推断适当的生存期.

经过一些研究,我发现了What is the correct way to return an Iterator (or any other trait)?个,这使我增加了+ 'a个:

fn into_iterator<'a>(myvec: &'a Vec<Foo>) -> Box<dyn Iterator<Item = &'a Foo> + 'a> {
    Box::new(myvec.iter())
}

但我不明白

  • 这是干什么的
  • 为什么这里需要它

推荐答案

有一件事很容易被忽略:如果你有一个trait Bar,并且你想要一个装箱的trait对象Box<dyn Bar>,编译器会自动添加一个'static的生存期界限(如RFC 599中所指定).这意味着Box<dyn Bar>Box<dyn Bar + 'static>是等效的!

在您的例子中,编译器会自动添加静态绑定,这样...

fn into_iterator(myvec: &Vec<Foo>) -> Box<dyn Iterator<Item = &Foo>>

... 相当于:

fn into_iterator(myvec: &Vec<Foo>) -> Box<dyn Iterator<Item = &Foo> + 'static>

现在,lifetime elision规则将启动并"连接"两个lifetime插槽,这样上面的代码就相当于:

fn into_iterator<'a>(myvec: &'a Vec<Foo>) -> Box<dyn Iterator<Item = &'a Foo> + 'static>

但是类型Iter<'a, Foo>(Vec<Foo>的特定迭代器类型)显然不满足边界'static(因为它borrow 了Vec<Foo>)!因此,我们必须告诉编译器,我们不希望通过指定自己的生存期界限来绑定默认的'static:

fn into_iterator<'a>(myvec: &'a Vec<Foo>) -> Box<dyn Iterator<Item = &Foo> + 'a>

现在编译器知道trait对象只在生存期'a内有效.请注意,我们不需要显式地注释关联Item类型的生存期!终身回避规则会解决这个问题.

Rust相关问答推荐

Tauri tauri—apps/plugin—store + zustand

展开枚举变量并返回所属值或引用

有没有办法避免在While循环中多次borrow `*分支`

如何在 struct 的自定义序列化程序中使用serde序列化_WITH

Tokio_Postgres行上未显示退回特性的生存期,且生命周期 不够长

在rust sqlx中使用ilike和push bind

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

`*mut[T]`与`*mut T`的区别

Rust 重写函数参数

Boxing 如何将数据从堆栈移动到堆?

Rust中的标记特征是什么?

从 Axum IntoResponse 获取请求标头

内部值发生变化时 Rc 的行为

当你删除一个存在于堆栈中的值时,为什么 rust 不会抱怨

在每个循环迭代中删除borrow

预期的整数,找到 `&{integer}`

没有通用参数的通用返回

在 Rust 中返回对枚举变体的引用是个好主意吗?

如何用另一个变量向量置换 rust simd 向量?

为什么 u64::trailing_zeros() 在无分支工作时生成分支程序集?