如何为 Box<dyn Stream<Item=()>> 使用地图?

One*_*ion 3 rust async-await

我有一段代码如下:

fn stream_it(&self) -> Box<dyn Stream<Item=()>> {
   Box::new(self.some_field)
}

fn consume_it(&self) {
   let a = self.stream_it().map(|i| i);
}
Run Code Online (Sandbox Code Playgroud)

我收到编译错误:

fn stream_it(&self) -> Box<dyn Stream<Item=()>> {
   Box::new(self.some_field)
}

fn consume_it(&self) {
   let a = self.stream_it().map(|i| i);
}
Run Code Online (Sandbox Code Playgroud)

我知道这个Sized要求是必要的,但我不知道如何满足它。甚至可以映射单元流吗?

Frx*_*rem 5

如果您查看 的定义StreamExt::map,该定义由实现 的类型自动实现Stream,您将看到:

fn map<T, F>(self, f: F) -> Map<Self, F>
where
    F: FnMut(Self::Item) -> T
Run Code Online (Sandbox Code Playgroud)

换句话说,map取得self. 但是Box<dyn Stream>没有实现Stream,所以它会尝试使用其中dyn Stream包含的值。但这是一个 trait 对象,它是一个未定义大小的类型,并且永远不会是self没有引用的参数,因此您的编译器错误。

这里的解决方案是将返回类型更改为Pin<Box<dyn Stream<Item = ()>>>,它确实实现了Stream

use std::pin::Pin;

fn stream_it() -> Pin<Box<dyn Stream<Item=()>>> {
//                ^-- add Pin<...> here
   Box::pin(futures::stream::iter(vec![(), (), ()]))
//      ^-- use Box::pin instead of Box::new
}
Run Code Online (Sandbox Code Playgroud)

或者,您也可以将返回类型更改为,这也确实实现了,但是对返回的流提出了一些额外的要求(即它实现了,因此可以安全地在内存中移动),因此通常不太可取。Box<dyn Stream<Item = ()> + Unpin>StreamUnpin

  • 这是可能的,因为所谓的“Deref”强制 - https://doc.rust-lang.org/1.30.0/book/2018-edition/ch15-02-deref.html - 以及方法调用的自动取消引用- /sf/ask/1996399821/ - 组合后,让我们将 `Box&lt;T&gt;` 视为 `T`。 (2认同)