如何在结构中存储`impl Trait`类型的变量? [英] How do I store a variable of type `impl Trait` in a struct?

查看:93
本文介绍了如何在结构中存储`impl Trait`类型的变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这有效:

let fut = Arc::new(Mutex::new(Box::pin(async { 1 })));

let mut conn_futures = BTreeMap::new(); // implicitly typed
conn_futures.insert(123, fut);
if let Some(fut) = conn_futures.get_mut(&123) {
   let fut = fut.clone();
   self.pool.spawn(async move {
        let mut fut = fut.try_lock().unwrap();
        (&mut *fut).await;
    });
};

我该如何在结构内部编写相同的内容; conn_futures是什么类型?根据编译器的说法,它是BTreeMap<i32, impl Future>,但是无法在结构中编写它:

How do I write the same thing inside a structure; what is the type of conn_futures? According to the compiler, it's BTreeMap<i32, impl Future>, but there's no way to write that in a structure:

struct Foo {
    conn_futures: BTreeMap<i32, impl Future>, // impl not allow in this position
}

我尝试过:

use futures::{executor::LocalPool, lock::Mutex, task::SpawnExt, Future}; // 0.3.1
use std::{collections::BTreeMap, pin::Pin, sync::Arc};

struct Foo {
    conn_futures: BTreeMap<i32, Arc<Mutex<Pin<Box<dyn Future<Output = i32>>>>>>,
}

fn alternative() {
    let mut pool = LocalPool::new();
    let spawner = pool.spawner();

    // Have a structure with the btreemap instead
    let mut foo = Foo {
        conn_futures: BTreeMap::new(),
    };
    let fut = Arc::new(Mutex::new(Box::pin(async { 1 })));
    foo.conn_futures.insert(123, fut);
    if let Some(fut) = foo.conn_futures.get_mut(&123) {
        let fut = fut.clone();
        spawner.spawn(async move {
            let mut fut = fut.try_lock().unwrap();
            (&mut *fut).await;
        });
    };
}

fn main() {
    let mut pool = LocalPool::new();
    let spawner = pool.spawner();
    let fut = Arc::new(Mutex::new(Box::pin(async { 1 })));

    let mut conn_futures = BTreeMap::new(); // implicitly typed
    conn_futures.insert(123, fut);
    if let Some(fut) = conn_futures.get_mut(&123) {
        let fut = fut.clone();
        spawner.spawn(async move {
            let mut fut = fut.try_lock().unwrap();
            (&mut *fut).await;
        });
    };
}

游乐场

出现错误

error[E0308]: mismatched types
  --> src/main.rs:17:34
   |
17 |     foo.conn_futures.insert(123, fut);
   |                                  ^^^ expected trait core::future::future::Future, found opaque type
   |
   = note: expected type `std::sync::Arc<futures_util::lock::mutex::Mutex<std::pin::Pin<std::boxed::Box<(dyn core::future::future::Future<Output = i32> + 'static)>>>>`
              found type `std::sync::Arc<futures_util::lock::mutex::Mutex<std::pin::Pin<std::boxed::Box<impl core::future::future::Future>>>>`

如何在结构中声明conn_futures的类型?

How do I declare the type of conn_futures in a struct?

推荐答案

您不能,真的. impl Trait创建一个匿名的,无法命名的类型.这意味着您不能使用将起作用的显式类型声明变量.

You cannot, really. impl Trait creates an anonymous, unnameable type. That means that you cannot declare a variable with an explicit type that will work.

主要解决方案是使用 trait对象:

use std::fmt::Display;

fn make_it() -> impl Display {
    2
}

struct Example {
    it: Box<dyn Display>,
}

impl Example {
    fn make() -> Self {
        Example {
            it: Box::new(make_it()),
        }
    }
}

您还可以避免使用关联的函数,而应将普通函数与泛型结合使用:

You can also avoid using an associated function and use a plain function instead, coupled with a generic:

use std::fmt::Display;

fn make_it() -> impl Display {
    2
}

struct Example<T> {
    it: T,
}

impl Example<Box<dyn Display>> {
    fn make() -> Self {
        Example {
            it: Box::new(make_it()),
        }
    }
}

fn make_example() -> Example<impl Display> {
    Example {
        it: make_it(),
    }
}

只在夜晚

如果您希望使用不稳定的夜间功能,则可以使用

Nightly only

If you wish to use unstable nightly features, you can use existential types (RFC 2071):

// 1.41.0-nightly (2019-11-24 412f43ac5b4ae8c3599e)
#![feature(type_alias_impl_trait)]

use std::fmt::Display;

type SomeDisplay = impl Display;

fn make_it() -> SomeDisplay {
    2
}

struct Example {
    it: SomeDisplay,
}

impl Example {
    fn make() -> Self {
        Example {
            it: make_it(),
        }
    }
}

或者:

// 1.41.0-nightly (2019-11-24 412f43ac5b4ae8c3599e)
#![feature(type_alias_impl_trait)]

use std::fmt::Display;

fn make_it() -> impl Display {
    2
}

struct Example<T> {
    it: T,
}

type SomeDisplay = impl Display;

impl Example<SomeDisplay> {
    fn make() -> Self {
        Example { it: make_it() }
    }
}

另请参阅:

  • What is the correct way to return an Iterator (or any other trait)?
  • Why can impl trait not be used to return multiple / conditional types?
  • Is it possible to use `impl Trait` as a function's return type in a trait definition?
  • What makes something a "trait object"?
  • What is the advantage of publishing a concrete type in a crate's API instead of `impl trait`?

这篇关于如何在结构中存储`impl Trait`类型的变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆