如何使用 Box> 的地图?

2024-04-21

我有一段代码如下:

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);
}

我收到编译错误:

error: the `map` method cannot be invoked on a trait object
   --> ...
    |
69  |       let a = self.stream_it().map(|i| i);
    |                                ^^^
    | 
   ::: ...
    |
257 |         Self: Sized,
    |               ----- this has a `Sized` requirement
    |
    = note: other candidates were found in the following traits, perhaps add a `use` for one_of_them:
            candidate #1: `use futures_util::future::future::FutureExt;`
            candidate #2: `use futures_signals::signal::signal::SignalExt;`
            candidate #3: `use futures_util::stream::stream::StreamExt;`
            candidate #4: `use futures_signals::signal_vec::SignalVecExt;`
            candidate #5: `use async_std::stream::stream::StreamExt;`

据我了解,Sized需求是必要的,但我不知道如何实现。甚至可以映射单元流吗?


如果你看一下定义StreamExt::map https://docs.rs/futures/0.3.4/futures/stream/trait.StreamExt.html#method.map,它由实现的类型自动实现Stream https://docs.rs/futures/0.3.4/futures/stream/trait.Stream.html,你会看到这个:

fn map<T, F>(self, f: F) -> Map<Self, F>
where
    F: FnMut(Self::Item) -> T

换句话说,map取得所有权self. But Box<dyn Stream>不执行Stream,因此它将尝试使用dyn Stream内含的价值。但这是一个特征对象,它是一个未调整大小的类型,并且永远不可能是一个self参数没有引用,因此编译器错误。

这里的解决方案是将返回类型更改为Pin https://doc.rust-lang.org/stable/std/pin/struct.Pin.html<Box<dyn Stream<Item = ()>>>, which does实施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
}

或者,您也可以将返回类型更改为Box<dyn Stream<Item = ()> + Unpin https://doc.rust-lang.org/stable/std/marker/trait.Unpin.html>,这也实现了Stream,但对返回的流提出了一些额外的要求(即它实现Unpin因此在内存中移动是安全的),因此通常不太可取。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Box> 的地图? 的相关文章

随机推荐