直接传递给宏模式的类型与您期望的方式匹配,但如果它们通过另一个宏传递,则它们会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));
}
Run Code Online (Sandbox Code Playgroud)
这打印ioo
而不是iiz
.
传递tt
s代替ty
s工作,但是如果&str
你需要2 tt
秒,使一切变得不必要地复杂化.
这不起作用,无法工作.
总结一下Rust Macros小书的Captures和Expansion Redux章节:问题是除了tt
和ident
捕获之外,macro_rules!
完全无法解构或检查捕获的令牌.一旦你捕获了某些东西ty
,它就会不可逆转地成为一个黑盒子macro_rules!
.
换句话说:就其而言,它&str
不是一种类型macro_rules!
:它是两个令牌,&
而且str
.但是当你捕获然后替换&str
为ty
,它变成了一个"元令牌":类型&str
.两者不再相同,因此不匹配.
如果您打算稍后匹配或破坏令牌,则必须将其捕获为tt
s或ident
s(如果可能).在这种特定情况下,您可以重写规则,around
而不是($($t:tt)*) => (mrtype!($($t)*));
保留原始令牌序列.