简体   繁体   中英

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.

Gives the error: 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")`

From looking into this, it seems that its not possible to expand a list inside a macro using a macro or 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();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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