Rust宏:调用依赖于表达式的函数

Rust宏:调用依赖于表达式的函数,rust,rust-macros,Rust,Rust Macros,我有三个不同的函数,我想根据宏参数调用其中一个。这个参数应该经过预处理,这就是为什么我认为我需要将它写成expr。然而,我似乎找不到一种方法来区分宏中expr的不同情况。这是我的密码: fn func_100(){ println!("Func 100!"); } fn func_200(){ println!("Func 200!"); } fn func_300(){ println!("Func 300!"); } macro_rules! generate_fu

我有三个不同的函数,我想根据宏参数调用其中一个。这个参数应该经过预处理,这就是为什么我认为我需要将它写成
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
表达式调用不同的函数?

您可以通过调用
cargo+nightly rustc--profile=check--Zunstable options--pretty=expanded
或使用

fn f1(){
{
::std::io::_打印(::std::fmt::Arguments::new_v1)(
&[“”,“\n”],
&匹配(&(100/100),){
(arg0,)=>[::std::fmt::ArgumentV1::new(arg0,::std::fmt::Debug::fmt)],
},
));
};
();
}
您可以看到最后一个
()应该是
func_100()

这是因为在类型为
($number:expr)
generate\u func\u call
中没有令牌规则,即没有与扩展匹配的规则。这是因为在函数中,
$number
不会被
100
替换。宏只是根据它接收到的数据创建更多的代码,它不尝试评估任何内容

将代码更改为:

macro\u规则!生成函数调用{
($number:expr)=>{
匹配$number{
100=>func_100(),
200=>func_200(),
300=>func_300(),
_ => (),
}
};
}
最后是
()更改为:

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

您不必担心额外的跳转语句之类的问题,它会得到优化,因为
300
是编译时常量。它只是变成了
func_300()

看起来它根本不受支持

一种可能的解决方法是匹配第一个宏中的文本,如下所示。尽管这只是引入了更多的代码重复

将来可能会使用类似于此的
const fn
功能来实现这一点。但你得等一等


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

匹配值,因为Rust编译器在优化方面非常好,所以如果在
if
表达式中使用常量,它将为您消除这一点,因此对运行时没有影响。非常相关(如果不是dup):可能重复