Reputation: 48248
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")`
Upvotes: 6
Views: 997
Reputation: 48248
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();
}
Upvotes: 5