gpt4 book ai didi

rust - 我可以将 `impl Future` 存储为具体类型吗?

转载 作者:行者123 更新时间:2023-12-05 02:41:09 25 4
gpt4 key购买 nike

tokio::net::TcpStream::connect是一个异步函数,意味着它返回一个存在类型,impl Future .我想存储一个 Vec这些 future 在一个结构中。我发现了很多问题,其中有人想要存储多个不同 impl Future s 在列表中,但我只想存储一个的返回类型。我觉得如果没有 Box<dyn Future> 这应该是可能的因为我实际上只存储了一个具体类型,但如果没有得到 found opaque type,我无法弄清楚如何做。错误。

最佳答案

夜间功能 min_type_alias_impl_trait 是可能的。诀窍是创建一个类型别名和一个虚拟函数,编译器可以从中推断出定义用途。

#![feature(min_type_alias_impl_trait)]

use tokio::net::TcpStream;
use core::future::Future;

type TcpStreamConnectFut = impl Future<Output = std::io::Result<TcpStream>>;

fn __tcp_stream_connect_defining_use() -> TcpStreamConnectFut {
TcpStream::connect("127.0.0.1:8080")
}

struct Foo {
connection_futs: Vec<TcpStreamConnectFut>,
}

这可以编译,但没有按预期工作:

impl Foo {
fn push(&mut self) {
self.connection_futs.push(TcpStream::connect("127.0.0.1:8080"));
}
}
error[E0308]: mismatched types
--> src/lib.rs:18:35
|
6 | type TcpStreamConnectFut = impl Future<Output = std::io::Result<TcpStream>>;
| ------------------------------------------------ the expected opaque type
...
18 | self.connection_futs.push(TcpStream::connect("127.0.0.1:8080"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found a different opaque type
|
= note: while checking the return type of the `async fn`
= note: expected opaque type `impl Future` (opaque type at <src/lib.rs:6:28>)
found opaque type `impl Future` (opaque type at </playground/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.7.1/src/net/tcp/stream.rs:111:56>)
= help: consider `await`ing on both `Future`s
= note: distinct uses of `impl Trait` result in different opaque types

使用我们创建的虚拟函数可以工作:

impl Foo {
fn push(&mut self) {
self.connection_futs.push(__tcp_stream_connect_defining_use());
}
}

所以我们可以创建包装函数:

fn tcp_stream_connect<A: ToSocketAddrs>(addr: A) -> TcpStreamConnectFut  {
TcpStream::connect(addr)
}

除了...

error: type parameter `A` is part of concrete type but not used in parameter list for the `impl Trait` type alias
--> src/main.rs:9:74
|
9 | fn tcp_stream_connect<A: ToSocketAddrs>(addr: A) -> TcpStreamConnectFut {
| __________________________________________________________________________^
10 | | TcpStream::connect(addr)
11 | | }
| |_^

我们可以只使用 String&'static str,然后整个编译:

type TcpStreamConnectFut = impl Future<Output = std::io::Result<TcpStream>>;

fn tcp_stream_connect(addr: &'static str) -> TcpStreamConnectFut {
TcpStream::connect(addr)
}

struct Foo {
connection_futs: Vec<TcpStreamConnectFut>,
}

impl Foo {
fn push(&mut self) {
self.connection_futs.push(tcp_stream_connect("..."));
}
}

您还可以将通用参数添加到类型别名本身,但在这种情况下这可能没有意义:

type TcpStreamConnectFut<A> = impl Future<Output = std::io::Result<TcpStream>>;

fn tcp_stream_connect<A: ToSocketAddrs>(addr: A) -> TcpStreamConnectFut<A> {
TcpStream::connect(addr)
}

struct Foo {
connection_futs: Vec<TcpStreamConnectFut<&'static str>>,
}

impl Foo {
fn push(&mut self) {
self.connection_futs.push(tcp_stream_connect("..."));
}
}

所以它可能的,但是有一些限制。我不确定其中有多少是错误,有多少是故意行为。已经讨论过关于 typeof 操作符来简化这件事,但这就是我们目前所拥有的。

关于rust - 我可以将 `impl Future` 存储为具体类型吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68216677/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com