直接传递给宏模式的类型与您期望的方式匹配,但如果它们通过另一个宏ty
传递,则它们会停止匹配:
macro_rules! mrtype {
( bool ) => ("b");
( i32 ) => ("i");
( f64 ) => ("f");
( &str ) => ("z");
( $_t:ty ) => ("o");
}
macro_rules! around {
( $t:ty ) => (mrtype!($t));
}
fn main() {
println!("{}{}{}", mrtype!(i32), around!(i32), around!(&str));
}
这会打印ioo
而不是iiz
。
传递tt
而不是ty
,但如果您&str
,则需要2 tt
秒,这会让所有内容变得不必要。
答案 0 :(得分:7)
这不起作用,无法工作。
总结Captures and Expansion Redux chapter of The Little Book of Rust Macros:问题在于tt
和ident
抓取除外,macro_rules!
完全无法解构或检查捕获的令牌。一旦你捕捉到ty
的内容,它就会不可逆转地成为macro_rules!
的黑盒子。
换句话说:&str
不是一种类型,就macro_rules!
而言:它是两个令牌,&
和str
。但是,当您捕获并将&str
替换为ty
时,它将成为单个“元令牌”:类型&str
。两者不再相同,因此不匹配。
如果您打算稍后匹配或破坏令牌,则必须将其捕获为tt
或ident
s(如果可能)。在此特定的情况下,您可以将around
的规则改为($($t:tt)*) => (mrtype!($($t)*));
,而不是%USERPROFILE%\AppData\Roaming\npm
,这会保留原始令牌序列。