我有三个不同的函数,我想根据宏参数调用其中一个函数。这个参数应该被预处理,这就是为什么我认为我需要将其写为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();
}
Run Code Online (Sandbox Code Playgroud)
这会生成以下编译时错误:
generate_func_call!($number);
^^^^^^^ no rules expected this token in macro call
Run Code Online (Sandbox Code Playgroud)
我如何修复这个程序,以便根据表达式调用不同的函数$number?
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)],
},
));
};
();
}
Run Code Online (Sandbox Code Playgroud)
你可以看到最后一个();应该是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(),
_ => (),
}
};
}
Run Code Online (Sandbox Code Playgroud)
最后();改为:
match 300 {
100 => func_100(),
200 => func_200(),
300 => func_300(),
_ => (),
};
Run Code Online (Sandbox Code Playgroud)
您不必担心额外的跳转语句等,它会像300编译时间常数一样得到优化。它只是变成了func_300()。