如何在宏中匹配方法?

5
< p > item 片段可以匹配函数,但如果函数的第一个参数是self的变体,即如果它是一个方法,则不会被识别为item

macro_rules! test {
    ( $fn:item ) => {}
}

// Ok
test! {
    fn foo() -> bool {
        true
    }
}

// Not ok
test! {
    fn foo(self) -> bool {
        true
    }
}

fn main() {}

如何匹配一个方法?

可能是编写包含匹配体的宏的重复问题。 - Tyfingr
2
@Tyfingr,请问您能否解释一下我提出的问题和您提供的链接之间的联系,因为我看不出来。 - Boiethios
impl块之外,fn foo(self) {}的意思是什么? - Peter Hall
一个带有self参数的函数不是一个项,但它周围的impl块是。 - Peter Hall
@PeterHall 这将被放置在 impl 块中。这是一个样板代码生成器。我将同时生成内在的 impl 和 trait impl。 - Boiethios
1个回答

4

一个带有 self 的函数不是一个项,因为它不能在没有 impl 块给 self 指定类型的情况下存在于顶层。

然而,周围的 impl 块是一个项。

要匹配这个函数,你需要将其分解,可能像这样:

macro_rules! test {
    ( fn $fn:ident ( self ) -> $ret:ty $body:block ) => {};
}

但是你必须在impl内部使用宏:

impl Foo {
    test! {
        fn foo(self) -> bool {
            true
        }
    }
}

在这里,您还需要处理许多可能的函数类型的排列组合,这可能会变得非常重复:

// 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
    ) => {};
}

还有一些没有考虑到生命周期和类型参数的情况。

通过将这些情况委托给另一个宏来实现代码重用可能会很棘手,因为您在宏内部没有自己的类型,所以可能无法消除重复,不幸的是。


是否可能使用单个片段匹配所有方法?我无法匹配impl块,因为我需要分别匹配通用类型和边界。 - Boiethios
我将使用您的解决方案。这很简单,因为函数签名始终相同。 - Boiethios

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接