rust 有没有办法在同一个函数中返回不同类型的结构体?

pgpifvop  于 2023-05-18  发布在  其他
关注(0)|答案(1)|浏览(142)

我尝试使用nannou crate来随机生成符号,但是在编写随机生成符号并将其存储到以下结构体中的函数时遇到了麻烦

struct Sigil<T,U>{
    major:Drawing<'static,T>,
    minor:Vec<Drawing<'static,U>>
}

我试着做以下事情

fn sigil_make<T,U>(app: &App)->Sigil<T,U>{
    let draw=app.draw();
    let mut sigil:Sigil<T,U>;
    match random::<u8>()%2 {
        0=>sigil.major=draw.ellipse(),
        1=>sigil.major=draw.polygon(),
        _=>println!("uh oh")
    }
    return sigil;
}

但是这不起作用,因为major期望的是T类型,而我试图将其设置为来自nannou的形状。
怎样做才是合适的呢?

jq6vz3qz

jq6vz3qz1#

这里一下子有好几个问题。我将列出它们沿着可能的解决方案。

  • 您允许调用者指定T类型,但您的函数本身已经知道该类型。
  • 只需省略T参数即可。(调用者指定U是什么可能是有意义的,因为您的函数没有。
  • 你调用的两个方法返回不同的类型,但Rust是静态类型的,需要一个 * 单一 * 类型。
  • 在运行时返回一种类型或另一种类型需要动态分派(通常被视为带有trait的Box<dyn _>)或“either”类型,例如每个可能的返回类型都有一个变体的枚举。
  • 这两个方法还捕获了app.draw()返回的Draw的生存期,但当函数返回时,Draw将被销毁。
  • 接受一个&Draw而不是一个&App,这将为您提供一个更长寿命的Draw
  • 您的match_臂也需要作为相同类型的东西进行评估。
  • 让这个手臂恐慌,或者返回Option。由于不可能有另一个值,我们可以使用内置的unreachable!宏来恐慌。
  • 或者,将1臂更改为_
  • 您部分初始化Sigil; minor字段未初始化,因此无法返回它。
  • 同时初始化minor
  • Sigil指定Drawing值的生存期为'static,但不保证为真。
  • Sigil添加生存期。

下面是一个如何解决这些问题的示例:

struct Sigil<'a, T, U> {
    major: Drawing<'a, T>,
    minor: Vec<Drawing<'a, U>>,
}

// See also the "either" crate, which provides an enum like this.
enum Either<L, R> {
    Left(L),
    Right(R),
}

fn sigil_make<U>(draw: &Draw) -> Either<Sigil<'_, Ellipse, U>, Sigil<'_, PolygonInit, U>> {
    match random::<u8>() % 2 {
        0 => Either::Left(Sigil {
            major: draw.ellipse(),
            minor: vec![],
        }),
        _ => Either::Right(Sigil {
            major: draw.polygon(),
            minor: vec![],
        }),
    }
}

相关问题