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)*)
    })
}

推荐答案

可以写build_fn个宏吗?

不能使用声明性宏,因为声明性宏必须生成an entire language item(语句、表达式、类型、模式等).

在这里,您试图生成一段元组,它不是Ruust语言中的一项.

使用过程性宏可能是可能的,因为IIRC过程性宏是根据令牌流操作的,所以虽然它们通常用于生成项,但它们might能够生成子项或部分项(我实际上从未以这种方式使用过它们).

Rust相关问答推荐

在actix—web中使用Redirect或NamedFile响应

常量泛型和类型枚举箱有重叠的用途吗?

MutexGuard中的过滤载体不需要克隆

为潜在的下游实现使用泛型绑定而不是没有泛型绑定的trait

如何在嵌套的泛型 struct 中调用泛型方法?

无法将 rust 蚀向量附加到另一个向量

为什么RefCell没有与常规引用相同的作用域?

在为第三方 struct 实现第三方特征时避免包装器的任何方法

如何重命名 clap_derive 中的子命令占位符?

在使用粗粒度锁访问的数据 struct 中使用 RefCell 是否安全?

结果流到 Vec 的结果:如何避免多个into_iter和collect?

sha256 摘要仅适用于 &*

Button.set_hexpand(false) 不会阻止按钮展开

为什么这个闭包没有实现Fn?

有没有办法通过命令获取 Rust crate 的可安装版本列表?

SDL2 没有在终端键上触发?

使用方法、关联函数和自由函数在 Rust 中初始化函数指针之间的区别

RAII 模式的 Rust 解决方案,用于在 new() 和 drop() 上修改另一个对象

隐式类型闭包的错误生命周期推断

如何在 Rust 的内置函数上实现特征?