2

我有三个不同的函数,我想根据宏参数调用其中一个。这个参数应该是预处理的,这就是为什么我认为我需要把它写成expr. 但是,我似乎无法找到一种方法来区分expr宏中的不同情况。这是我的代码:

fn func_100(){
    println!("Func 100!");
}
fn func_200(){
    println!("Func 200!");
}
fn func_300(){
    println!("Func 300!");
}

macro_rules! generate_func_call {
    (100) => {
        func_100();
    };
    (200) => {
        func_200();
    };
    (300) => {
        func_300();
    }
}

macro_rules! generate_func_call_wrapper {
    ($func: ident, $number: expr) => {
        fn $func(){
            println!("{:?}", $number / 100);
            generate_func_call!($number);
        }
    };
}

generate_func_call_wrapper!(f1,100);
generate_func_call_wrapper!(f2,200);
generate_func_call_wrapper!(f3,300);

fn main(){
    f1();
}

这会产生以下编译时错误:

    generate_func_call!($number);
                        ^^^^^^^ no rules expected this token in macro call

如何修复这个程序,以便根据$number表达式调用不同的函数?

4

2 回答 2

3

cargo +nightly rustc --profile=check -- -Zunstable-options --pretty=expanded您可以通过调用或使用cargo-expand来查看宏扩展

fn f1() {
    {
        ::std::io::_print(::std::fmt::Arguments::new_v1(
            &["", "\n"],
            &match (&(100 / 100),) {
                (arg0,) => [::std::fmt::ArgumentV1::new(arg0, ::std::fmt::Debug::fmt)],
            },
        ));
    };
    ();
}

你可以看到最后();一个应该是func_100()

generate_func_call这是因为类型中没有标记规则,($number: expr)即没有与扩展匹配的规则。这是因为不会像您在函数中所期望的那样$number被替换。100宏只是根据它收到的片段类型创建更多的 rust 代码,它不会尝试评估任何内容。

将代码更改为:

macro_rules! generate_func_call {
    ($number: expr) => {
        match $number {
            100 => func_100(),
            200 => func_200(),
            300 => func_300(),
            _ => (),
        }
    };
}

最后();更改为:

match 300 {
    100 => func_100(),
    200 => func_200(),
    300 => func_300(),
    _ => (),
};

您不必担心额外的跳转语句等,它会像300编译时间常数一样得到优化。它只是变成func_300().

于 2019-04-23T08:44:22.977 回答
0

看起来它根本不支持。

类似问题 #1 类似问题 #2

一种可能的解决方法是匹配第一个宏中的文字,就像在这个playground中一样。虽然这只是引入了更多的代码重复。

将来可能会使用这个Playgroundconst fn中的功能来做到这一点。但是您必须等待该功能被实施

现在我建议在运行时使用常规的match.

于 2019-04-23T09:17:53.113 回答