简体   繁体   English

如何将包含多个项目的宏传递到宏?

[英]How to pass a macro containing multiple items into a macro?

Given this simple macro that expands multiple items, how could this take a macro as an argument? 鉴于这个扩展多个项目的简单宏,如何将宏作为参数?

macro_rules! print_structs {
    ($($t:ty)*) => ($(
        println!("{:?}", TypeId::of::<$t>());
    )*)
}

// expands one println per type!
print_structs! { i8 i16 usize String }

How could a pre-defined macro of types be passed in? 如何传入预定义的类型宏?

Example of non-working macro: 非工作宏的示例:

macro_rules! some_types {
    () => {
        i8 i16 usize String
    }
}

print_structs! { some_types!() }

See play.rust-lang.org example, uncomment UNCOMMENT TO TEST lines to see the problem. 请参阅play.rust-lang.org示例,取消注释UNCOMMENT TO TEST行以查看问题。

Gives the error: macro expansion ignores token `i16` and any following 给出错误: macro expansion ignores token `i16` and any following


I also tried to put the list in a file to include, eg: 我还尝试将列表放在一个文件中,例如:

print_structs! {
    include!("some_types.in")
}

... however this gives an error: expected type, found `include!("../struct_list.rs")` ...但是这给出了一个错误: expected type, found `include!("../struct_list.rs")`

From looking into this, it seems that its not possible to expand a list inside a macro using a macro or include . 从这看起来,似乎不可能使用宏或include扩展宏内的列表。

Although code-generation is an option, its quite involved so will leave it out of this answer. 虽然代码生成是一种选择,但它非常复杂,所以会将其排除在此答案之外。

It is possible to get similar functionality by swapping macro use around, instead of passing the list into a macro, pass a macro name into a generic macro that expand it with a list. 可以通过交换宏使用来获得类似的功能,而不是将列表传递到宏中,将宏名称传递给通用宏,使用列表扩展它。

Heres a working example: 下面是一个有效的例子:

macro_rules! print_structs {
    ($($t:ty)*) => ($(
        println!("{:?}", ::std::any::TypeId::of::<$t>());
    )*)
}

macro_rules! apply_macro_to_structs {
    ($macro_id:ident) => {
        $macro_id! {
            i8 i16 usize String
        }
    }
}

fn test_a() {
    // expands one println per type!
    print_structs! { i8 i16 usize String }
}

fn test_b() {
    // expand using a macro
    apply_macro_to_structs!(print_structs);

}

fn main() {
    test_a();
    test_b();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM