该item片段可以匹配函数,但是如果函数的第一个参数是的变体self,即如果它是方法,则不能将其识别为item:
macro_rules! test {
( $fn:item ) => {}
}
// Ok
test! {
fn foo() -> bool {
true
}
}
// Not ok
test! {
fn foo(self) -> bool {
true
}
}
fn main() {}
Run Code Online (Sandbox Code Playgroud)
如何搭配方法?
接受的函数不是一个项目,因为如果没有一个块来为 提供类型,self它就不能存在于顶层。implself
不过,周围的impl块是一个项目。
为了匹配该功能,您必须将其分解,也许像这样:
macro_rules! test {
( fn $fn:ident ( self ) -> $ret:ty $body:block ) => {};
}
Run Code Online (Sandbox Code Playgroud)
但你必须在块内使用宏impl:
impl Foo {
test! {
fn foo(self) -> bool {
true
}
}
}
Run Code Online (Sandbox Code Playgroud)
不过,您还必须在这里处理相当多可能类型的函数的排列,这最终可能会变得非常重复:
// enables the ? operator for optional parts
#![feature(macro_at_most_once_rep)]
macro_rules! test {
( fn $fn:ident ( $($name:ident : $type:ty),* ) $( -> $ret:ty )?
$body:block
) => {};
( fn $fn:ident ( self $(, $name:ident : $type:ty)* ) $( -> $ret:ty )?
$body:block
) => {};
( fn $fn:ident ( &self $(, $name:ident : $type:ty)* ) $( -> $ret:ty )?
$body:block
) => {};
( fn $fn:ident ( &mut self $(, $name:ident : $type:ty)* ) $( -> $ret:ty )?
$body:block
) => {};
}
Run Code Online (Sandbox Code Playgroud)
这些甚至不考虑生命周期或类型参数。
通过将这些情况委托给另一个宏来实现代码重用可能会很棘手,因为您没有 self宏内部的类型,因此不幸的是,您可能无法摆脱重复。