Macros 在宏中构建枚举

Macros 在宏中构建枚举,macros,rust,Macros,Rust,是否可以使用定义为宏参数的字段在Rust宏中构建枚举?我试过这个: macro_rules! build { ($($case:ty),*) => { enum Test { $($case),* } }; } fn main() { build!{ Foo(i32), Bar(i32, i32) }; } 但它失败,出现错误:预期标识,找到'Foo(i32) 请注意,如果字段是在枚举中定义的,则没有问题: macro_rules! build { ($($ca

是否可以使用定义为宏参数的字段在Rust宏中构建枚举?我试过这个:

macro_rules! build {
    ($($case:ty),*) => { enum Test { $($case),* } };
}

fn main() {
    build!{ Foo(i32), Bar(i32, i32) };
}
但它失败,出现
错误:预期标识,找到'Foo(i32)

请注意,如果字段是在枚举中定义的,则没有问题:

macro_rules! build {
    ($($case:ty),*) => { enum Test { Foo(i32), Bar(i32, i32) } };
}

fn main() {
    build!{ Foo(i32), Bar(i32, i32) };
}
如果“我的宏”只接受简单字段,它也可以工作:

macro_rules! build {
    ($($case:ident),*) => { enum Test { $($case),* } };
}

fn main() {
    build!{ Foo, Bar };
}

但在一般情况下,我无法让它工作。

这是绝对可能的,但你把完全不相关的概念混为一谈了

类似于
$case:ty
的东西并不意味着
$case
看起来像一种类型,它意味着
$case
实际上是一种类型。枚举不是由一系列类型组成的;它们由一系列变体组成,这些变体是一个标识符,后跟(可选)元组结构体、记录结构体或标记值

解析器并不关心您给它的类型是否恰好看起来像一个有效的变量,它只是不需要类型,并且会拒绝在该位置解析一个类型

您需要的是使用类似于
$case:variant
的东西。不幸的是,你不存在这样的匹配者。这样做的唯一方法是使用递归增量解析器手动解析它,这超出了so问题的范围,一点也不好笑。如果您想了解更多信息,请尝试将此作为起点

然而,您似乎并没有实际处理这些案例。你只是在盲目地替换它们。在这种情况下,您可以作弊,而不必费心尝试匹配任何连贯的内容:

macro\u规则!建造{
($($正文:tt)*)=>{
作为商品{
枚举测试{$($body)*}
}
};
}
宏规则!作为项目{
($i:项目)=>{$i};
}
fn main(){
建造!{Foo,Bar};
}
(顺便说一句,
as_item!
这件事在(又称“重分析技巧”)一节中有解释。)

这只是获取作为
build的输入提供的所有内容
,并将其推入
枚举的主体中,而不关心它的外观


如果您试图对这些变体做一些有意义的事情,那么,您必须这样做,因为关于如何进行的最佳建议因答案而异。

我们确实需要将Rust Macros小册子提升到官方文档级别,以使您的辛勤工作更容易找到!谢谢,我已经广泛使用了tlborm,但在本例中,我正在考虑可以在
enum{}
中添加的内容(即
enum{as_something!($($body)*)}
没有意识到需要将整个枚举包装成
作为_项
。非常感谢tlborm,如果没有它,我就不会使用rust宏了。为什么这个示例在
=>之后使用
{}
,而所有TRPL书籍示例都使用