rust 当每个分支返回一个类型与一个类型参数的不同组合时,我如何减少2个嵌套的匹配语句

mnowg1ta  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(64)

我的问题是:我有一个返回Box<dyn Trait_1>-对象的函数。假设我在级别1有N=2可能的类型,它们实现了这个Trait_1,我希望这两个类型都可以通过match语句访问。但是现在这两个可能的类型也都是泛型的。(但必须实现Trait_2)我有M=2可能的类型在第2级,我想使用。现在我可以有一个匹配与4臂或2嵌套匹配与2臂。我必须写4个语句,初始化这个Box。这很简单。但是如果我在级别1有N=15类型(impl Trait_1),在级别2有20个类型,impl其他一些Trait_2,我最终会编写300个不同的初始化!这是一个很大的工作,而且我可能会输入一些错误。
我已经写了一个简单的例子,我的问题有2个嵌套的匹配语句,每个语句有2个分支,总共有4个初始化(我省略了Trait实现)

pub trait Trait_1 {}
pub trait Trait_2 {}

pub struct SingleContainer<T: Trait_2> {
    item: T,
}

pub struct DoubleContainer<T: Trait_2> {
    item_1: T,
    item_2: T,
}

// -> impl Trait_1 for SingleContainer and DoubleContainer

struct X {
    number: f64,
}

struct Y {
    number: u32,
}

// -> impl Trait_2 for X and Y

fn main() {
    let a = // determined at runtime
    let b = // determined at runtime

    let thing = give_thing(a, b);
}

fn give_thing(thing_number: usize, thing_name: &str) -> Box<dyn Trait_1> {
    match thing_number {
        1 => match thing_name {
            "X" => Box::new(SingleContainer::<X>::default()),
            "Y" => Box::new(SingleContainer::<Y>::default()),
            _ => todo!(),
        },
        2 => match thing_name {
            "X" => Box::new(DoubleContainer::<X>::default()),
            "Y" => Box::new(DoubleContainer::<Y>::default()),
            _ => todo!(),
        },
        _ => todo!(),
    }
}

字符串
有没有更好的方法来做到这一点?我很难看到另一种方法,因为这些东西都是不同的类型。我希望在编译时,(SingleContainer,DoubleContainer)和(X,Y)“exists”,因此将被优化。如果有更好的方法来实现这一点,请让我知道!我基本上只需要一个函数返回一个Box<dyn MyTrait>对象,它有两个参数。但是每个参数组合返回一个不同的类型,我很困惑!
编辑:在这种情况下,全面实现会有帮助吗?
(If有人有更好的措辞我的问题,随时纠正我!)

p8h8hvxi

p8h8hvxi1#

在这里,一点类型元编程可以提供帮助。

trait MakeTrait1 {
    type Make<T: Trait_2 + Default + 'static>: Trait_1 + Default + 'static;
}

struct MakeSingleContainer;
impl MakeTrait1 for MakeSingleContainer {
    type Make<T: Trait_2 + Default + 'static> = SingleContainer<T>;
}

struct MakeDoubleContainer;
impl MakeTrait1 for MakeDoubleContainer {
    type Make<T: Trait_2 + Default + 'static> = DoubleContainer<T>;
}

fn make_trait1<T: MakeTrait1>(thing_name: &str) -> Box<dyn Trait_1> {
    match thing_name {
        "X" => Box::new(T::Make::<X>::default()),
        "Y" => Box::new(T::Make::<Y>::default()),
        _ => todo!(),
    }
}

fn give_thing(thing_number: usize, thing_name: &str) -> Box<dyn Trait_1> {
    match thing_number {
        1 => make_trait1::<MakeSingleContainer>(thing_name),
        2 => make_trait1::<MakeDoubleContainer>(thing_name),
        _ => todo!(),
    }
}

字符串
Playground的一个。
我们基本上创建了一个类型工厂,内部类型创建了外部类型,然后我们有了一个函数,它根据这个类型工厂来做出运行时决策,剩下要做的就是有一个函数来调用每个工厂的这个函数。

相关问题