美文网首页
Rust for cpp dev - 宏

Rust for cpp dev - 宏

作者: 找不到工作 | 来源:发表于2021-05-24 18:47 被阅读0次

    宏是一种可以生成代码的代码,这种形式被称为“元编程”(metaprogramming)。我们已经使用过 Rust 中的多个宏,例如 println!, vec!, #[derive]等。这些宏都会在编译预处理时展开来生成代码。

    Rust 中的宏有多个种类,最常用的是“声明型宏”(declarative macros),此外还有三种“过程型宏”(procedural macros):

    • 通过 #[derive] 为结构体或者枚举类型添加代码
    • 属性
    • 函数

    声明型宏

    声明型宏会比较传入的表达式是否符合格式要求,如果符合则用传入的表达式替换宏中的 placeholder。

    例如,我们仿照 vec! 宏实现一个简单的 my_vec! 宏:

    // brings macro into the scope
    #[macro_export]
    
    macro_rules! my_vec {
        // similar to "match" expression
        ( $( $x:expr ),* ) => {
            // if pattern matches, below code is emitted
            {  // this "{}" is needed because the macro will be used in a one-line expression
                let mut temp_vec = Vec::new();
                $(
                    temp_vec.push($x);
                )*
                temp_vec
            }
        };
    }
    

    使用方式和 vec! 一致:

    use macros::my_vec;
    
    fn main() {
        let v = my_vec![1, 3, 5];
        println!("Hello, {:?}!", v);
    }
    

    现在来分析代码中的关键点。

    • 类似于 match 的结构,根据不同的模式生成不同代码,上面只匹配一种模式

    • ( $( $x:expr ),* ) 是一种模式。expr 指 Rust 表达式,这里将匹配 Rust 表达式并赋值给 $x 变量,, 就是指 , 字符,* 表示可以出现任意次或者不出现。基本类似于正则表达式。结果是,当我们调用 my_vec![1, 3, 5] 时,$x 匹配到了 1, 3, 5

    • $(temp_vec.push($x);)* 表明,模式匹配成功多少次,就对 $x 调用多少次 temp_vec.push($x)。对于 my_vec![1, 3, 5],生成的代码是:

    {
        let mut temp_vec = Vec::new();
        temp_vec.push(1);
        temp_vec.push(3);
        temp_vec.push(5);
        temp_vec
    }
    

    macro_rules! 有一些 edge case 不好处理,Rust 会在将来用更好的实现代替它。实际上,对于大部分的开发者而言,Rust 鼓励大家去使用 macro 而不是自己编写 macro。

    过程型宏

    (编写中)

    相关文章

      网友评论

          本文标题:Rust for cpp dev - 宏

          本文链接:https://www.haomeiwen.com/subject/hlpxsltx.html