是否可以为作为 Rust 宏参数给出的每个列表项创建匹配臂?

问题描述 投票:0回答:1

我想使用宏创建匹配。我不知道该怎么做,因为我似乎错过了宏如何处理元素列表(或者也许我做错了其他事情)。 我的用例:我有 N 个通用类型,例如

MyStructA<X: MyTraitTwo>, MyStructB<X: MyTraitTwo>, MyStructC<X: MyTraitTwo>
(实现了特征
TraitOne
),我使用泛型类型作为参数X。我想要有N个匹配臂(对于每个结构
MyStruct?
)。我的实际用例有嵌套匹配,例如X 的 M 种不同类型。因此,我必须手动编写 N * M 匹配臂。但首先是非嵌套的情况:

fn create_type(arg: &str) -> impl MyTrait {
    make_match_arms![("a", MyStructA),("b", MyStructB), ("c", MyStructC)];
}

// would expand to:
fn create_type(arg: &str) -> impl MyTraitOne {
    match => arg {
        "a" => MyStructA<X>::new(),
        "b" => MyStructB<X>::new(),
        "c" => MyStructC<X>::new(),
    }
}

理想情况下,我什至可以将其简化为两个类型列表,并将其提供给宏,该宏将为这两个元素的每个组合创建匹配臂。像这样(我省略了泛型,因为我不确定它们是否可以使用)。

match (first_type_str, second_type_str) => {
every_combination![(MyStructA, MyStructB, MyStructC), (X1, X2, X3, X4, X5)]
};

它看起来像这样:

fn return_combined_type(first: &str, second: &str) -> impl TraitOne<TraitTwo> {
    match first => {
        "a" => { 
                   match second => {
                       "1" => {MyStructA::<X1>::new(),
                       "2" => {MyStructA::<X2>::new(),
                       ...
                   },
        "b" => {
                   match second => {
                       "1" => { MyStructB::<X1>::new(),
                       ...
        ...

这将创建 15 个火柴臂 - 嵌套在 2 个火柴中。当然,我必须提供一个论点,即手臂与 (

first
,
second
) 也与宏相匹配,但我现在不确定如何执行此操作。 我不确定我是否能正确解释这一点。也许有人能够读懂字里行间并理解我的问题。

rust macros match
1个回答
0
投票

这是一个部分答案,使用重复,仅涵盖您问题的第一部分:

#[allow(unused)]

fn main() {
    macro_rules! make_match_arms {
        ($arg:expr, $(($s:literal, $id:ident)),*) => {
            {match $arg {
                $(
                    $s => Box::new($id::<X>::new()),
                )*
                _ => panic!()
            }}
        }
    }
    
    struct MyStructA<T>(T);
    struct MyStructB<T>(T);
    struct MyStructC<T>(T);
    impl<T: Default> MyStructA<T> { fn new() -> Self { Self(Default::default()) } }
    impl<T: Default> MyStructB<T> { fn new() -> Self { Self(Default::default()) } }
    impl<T: Default> MyStructC<T> { fn new() -> Self { Self(Default::default()) } }
    trait MyTrait {}
    impl<T> MyTrait for MyStructA<T> {}
    impl<T> MyTrait for MyStructB<T> {}
    impl<T> MyTrait for MyStructC<T> {}

    fn create_type<X: Default + 'static>(arg: &str) -> Box<dyn MyTrait> {
        make_match_arms![arg, ("a", MyStructA),("b", MyStructB), ("c", MyStructC)]
    }
}

我不知道宏有什么方法可以从两个列表自动生成每个组合,所以我看不到不涉及冗余的第二部分的答案。

© www.soinside.com 2019 - 2024. All rights reserved.