fn foo<T> { println!("foo: {:?}", std::any::type_name::<T>()); }
let functions = (foo::<i32>,build_fn!(i64,u64,f32,f64;foo),foo::<u32>);
// the final `functions` is
let functions = (foo::<i32>, foo::<i64>, foo::<u64>, foo::<f32>, foo::<f64> ,foo::<u32>);
// maybe more complex like build_fn!(i64,u64,f32,f64;foo,boo)
可以写build_fn
个宏吗?
--编辑行-
在我的 case 中,我是在和贝弗一起做一些事情.我设法弄到了这样的东西.这是一个很小的后退解决方案,但由于Bevy ECS的灵活性,它仍然有效.
macro_rules! unit_team_system {
($($team:ty),* ; $sys:tt) => {
($(unit_team_system!(@make_fun $team; $sys),)*)
};
(@make_fun $team:ty; ($($sys:ident),* $(,)?) ) =>{
($($sys::<$team>,)*)
};
}
#[derive(Debug)]
struct TeamA;
#[derive(Debug)]
struct TeamB;
#[derive(Debug)]
struct TeamC;
fn system_a<T>() {
println!("system_a: {:?}", std::any::type_name::<T>());
}
fn system_b<T>() {
println!("system_b: {:?}", std::any::type_name::<T>());
}
fn main() {
let systems = unit_team_system!(TeamA, TeamB, TeamC;
(
system_a,
system_b,
)
);
systems.1.0();
}
----------------- proc_macro -----------------
Still not posssible to generate subitems of a tuple.
extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
use syn::{Ident, Token, Type};
use syn::parse::{Parse, ParseStream};
struct UnitTeamSystem {
teams: Vec<Type>,
systems: Vec<Ident>,
}
impl Parse for UnitTeamSystem {
fn parse(input: ParseStream) -> syn::Result<Self> {
let mut teams = Vec::new();
let mut systems = Vec::new();
while !input.is_empty() {
if input.peek(Token![;]) {
break;
}
if input.peek(Token![,]) {
input.parse::<Token![,]>()?;
}
let team: Type = input.parse()?;
teams.push(team);
}
input.parse::<Token![;]>()?;
while !input.is_empty() {
let system: Ident = input.parse()?;
systems.push(system);
if input.peek(Token![,]) {
input.parse::<Token![,]>()?;
}
}
Ok(UnitTeamSystem {
teams,
systems,
})
}
}
#[proc_macro]
pub fn unit_team_system(input: TokenStream) -> TokenStream {
let UnitTeamSystem { teams, systems } = syn::parse_macro_input!(input as UnitTeamSystem);
let mut tokens = Vec::with_capacity(teams.len());
for team in teams {
for system in &systems {
tokens.push(quote! {
#system::<#team>,
});
}
}
eprintln!("{:?}", tokens);
TokenStream::from(quote! {
(#(#tokens)*)
})
}