本文介绍了为什么需要使用加号运算符 (Iterator<Item = &amp;Foo> + 'a) 为 trait 添加生命周期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在迭代器上应用了一个闭包,我想使用稳定版,所以我想返回一个装箱的Iterator.这样做的明显方法如下:

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

这会失败,因为借用检查器无法推断适当的生命周期.

经过一些研究,我发现返回迭代器(或任何其他特征)的正确方法是什么?,这让我添加了 + 'a:

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

但我不明白

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

解决方案

有一件事很容易被忽视:如果你有一个 trait Bar 并且你想要一个装箱的 trait 对象 Box<dyn Bar>,编译器会自动添加一个 'static 生命周期绑定(如 RFC 599).这意味着 BoxBox 是等价的!

在您的情况下,编译器会自动添加静态边界,以便 ...

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

... 等价于:

fn into_iterator(myvec: &Vec) ->Box+ '静态>

现在生命周期省略规则开始并连接"两个生命周期槽,这样上面的代码就相当于:

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

但是类型Iter(Vec的具体迭代器类型)显然不满足绑定的'static(因为它借用了 Vec)!所以我们必须通过指定我们自己的生命周期绑定来告诉编译器我们不希望默认的 'static 绑定:

fn into_iterator(myvec: &'a Vec) ->Box+ 'a>

现在编译器知道 trait 对象只在生命周期 'a 内有效.请注意,我们不需要明确注释关联的 Item 类型的生命周期!终生省略规则可以解决这个问题.

I'm applying a closure on the iterator and I want to use stable, so I want to return a boxed Iterator. The obvious way to do so is the following:

struct Foo;

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

This fails because the borrow checker cannot infer the appropriate lifetimes.

After some research, I've found What is the correct way to return an Iterator (or any other trait)?, which brought me to adding + 'a:

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

But I don't understand

  • What this does
  • And why it is needed here

解决方案

There is one thing that is easily overlooked: if you have a trait Bar and you want to have a boxed trait object Box<dyn Bar>, the compiler automatically adds a 'static lifetime bound (as specified in RFC 599). This means that Box<dyn Bar> and Box<dyn Bar + 'static> are equivalent!

In your case, the compiler automatically adds the static bound such that this ...

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

... is equivalent to that:

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

Now lifetime elision rules kick in and "connect" the two lifetime-slots, such that the above code is equivalent to:

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

But the type Iter<'a, Foo> (the specific iterator type for Vec<Foo>) obviously does not satisfy the bound 'static (because it is borrowing the Vec<Foo>)! So we have to tell the compiler that we don't want the default 'static bound by specifying our own lifetime bound:

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

Now the compiler knows that the trait object is only valid for the lifetime 'a. Note that we don't explicitly need to annotate the lifetime of the associated Item type! Lifetime elision rules take care of that.

这篇关于为什么需要使用加号运算符 (Iterator<Item = &amp;Foo> + 'a) 为 trait 添加生命周期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 11:24