rust - 从创建结构的宏的参数访问 self

标签 rust

我正在尝试编写一个生成结构的宏。该结构的实现将由宏生成,但一些代码块将作为宏参数提供。这是此类宏的最小示例:

macro_rules! make_struct {
    ($name:ident $block:block) => {
        struct $name {
            foo: i32,
        }

        impl $name {
            fn new() -> Self {
                $name { foo: 42 }
            }
            fn act (&self) {
                $block
            }
        }
    };
}

下面是如何使用宏的示例:

fn main() {
    // Works
    make_struct!(Test { println! ("Bar: {:?}", 24); });
    let test = Test::new();
    test.act();
}

我想在提供的代码中授予对 self 的访问权限。像这样的东西:

fn main() {
    // Does not work
    make_struct!(Test { println! ("Foo: {:?}", self.foo); });
    let test = Test::new();
    test.act();
}

我知道这不起作用,因为宏观卫生规则。具体来说,self.foo 表达式是在 main 函数的语法上下文中计算的,其中 self 不存在。问题是:有没有办法修改宏,以便可以从用户提供的代码访问 self

Code on playground

最佳答案

您可以传递闭包而不是 block 。

make_struct!(Test |this| println!("Foo: {:?}", this.foo));

然后宏可以使用闭包并用self调用它:

macro_rules! make_struct {
    ($name:ident $closure:expr) => {
        struct $name {
            foo: i32,
        }

        impl $name {
            fn new() -> Self {
                $name { foo: 42 }
            }
            fn act (&self) {
                let x: &Fn(&Self) = &$closure;
                x(self)
            }
        }
    };
}

与 let 绑定(bind)的舞蹈是必要的,因为无法推断闭包中 this 的类型(还?)。当传递闭包以外的内容时,它还使宏的错误报告更具可读性。

关于rust - 从创建结构的宏的参数访问 self,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36056408/

相关文章:

使用rust (Bevy) : ECS Network data structure

rust - 在 Rust 中,当装箱作为通用参数传递的值时,为什么需要 `' 静态生命周期边界?

json - 如何在Rust中搜索和解析任意长的JSON文件?

scope - 错误: "use of moved value"

xml - 使用 serde-xml-rs 反序列化 XML 会产生 Err(重复字段 `$value` )

rust - Substrate 运行时中不同模块调用 `on_initialize` 的顺序是什么?

module - 如何从私有(private)模块中的公共(public)函数引用私有(private)类型?

arrays - 暂时将[u8]转换为[u16]

rust - 如何在 Rust 中将类型参数指定为函数参数?

memory-management - 我可以通过持有引用来避免克隆字符串吗?