提问人:exocortex 提问时间:10/28/2023 更新时间:10/29/2023 访问量:47
当每个 arm 返回带有类型参数的类型的不同组合时,如何减少 2 个嵌套匹配语句
How can I reduce 2 nested match statements when each arm returns a different combination of a type with a type argument
问:
我的问题:我有一个返回-object的函数。假设我在级别 1 上有实现此目的的可能类型,并且我希望通过 match 语句访问这两种类型。但是现在这 2 种可能的类型也是通用的(但必须实现),并且我想在 2 级使用可能的类型。现在,我可以有一个 4 个臂的匹配项,也可以有 2 个嵌套的匹配项,每个组有 2 个臂。我必须写 4 个语句来初始化它。这很简单。但是,如果我在级别 1(实现 Trait_1)有类型,在级别 2 有 20 个类型,实现其他类型,我最终会编写 300 个不同的初始化!这是很多工作,而且我可能会犯一些错误。Box<dyn Trait_1>
N=2
Trait_1
Trait_2
M=2
Box
N=15
Trait_2
我写了一个简单的例子来说明我的问题,其中有 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)的每个可能的组合都“存在”,因此将得到优化。如果有更好的方法可以实现这一目标,请告诉我!我基本上只需要一个返回一个获得 2 个参数的 -object 的函数。但是由于每个参数组合返回不同的类型,我感到非常困惑!Box<dyn MyTrait>
编辑:在这种情况下,一揽子实现会以任何方式提供帮助吗?
(如果有人有更好的方式来表达我的问题,请随时纠正我!
答:
在这里,一个小类型的元编程可以提供帮助。
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!(),
}
}
游乐场。
我们基本上创建了一个类型工厂,该工厂为内部类型创建外部类型。然后我们有一个函数,它基于这个类型级工厂做出运行时决策,剩下要做的就是有一个函数,在每个工厂中调用这个函数。
评论
,如果您只有两个案例,或者如果您有更多案例,则自定义)。
Box<dyn Trait>
enum
enum