是否可以使用定义为宏参数的字段在Rust宏内构建枚举?我试过这个:
macro_rules! build {
($($case:ty),*) => { enum Test { $($case),* } };
}
fn main() {
build!{ Foo(i32), Bar(i32, i32) };
}
Run Code Online (Sandbox Code Playgroud)
但它失败了 error: expected ident, found 'Foo(i32)'
请注意,如果在枚举内定义了字段,则没有问题:
macro_rules! build {
($($case:ty),*) => { enum Test { Foo(i32), Bar(i32, i32) } };
}
fn main() {
build!{ Foo(i32), Bar(i32, i32) };
}
Run Code Online (Sandbox Code Playgroud)
如果我的宏只接受简单字段,它也有效:
macro_rules! build {
($($case:ident),*) => { enum Test { $($case),* } };
}
fn main() {
build!{ Foo, Bar };
}
Run Code Online (Sandbox Code Playgroud)
但是我一直无法让它在一般情况下工作.
这绝对是可能的,但你把完全不相关的概念混为一谈.
喜欢的东西$case:ty并不意味着$case是一些东西,看起来像一个类型,它的意思$case是字面上的一种类型.枚举不是一系列类型的; 它们由一系列变体组成,这些变体是一个标识符,后跟(可选)由元组结构体,记录结构体或标记值组成.
解析器并不关心你给它的类型是否恰巧看起来像一个有效的变体,它只是不期望一个类型,并且将拒绝在该位置解析一个类型.
你需要的是使用类似的东西$case:variant.不幸的是,没有这样的匹配器存在.做这样的事情的唯一方法是使用递归增量解析器手动解析它,就是这么出来的一个范围,从而质疑其不好笑.如果您想了解更多信息,请尝试使用Rust Book的Little Book中的增量TT munchers一章作为起点.
但是,您似乎没有对案例实际执行任何操作.你只是盲目地代替他们.在这种情况下,你可以只是作弊,而不是试图匹配任何连贯的东西:
macro_rules! build {
($($body:tt)*) => {
as_item! {
enum Test { $($body)* }
}
};
}
macro_rules! as_item {
($i:item) => { $i };
}
fn main() {
build!{ Foo, Bar };
}
Run Code Online (Sandbox Code Playgroud)
(顺便提一下,这个as_item!东西在AST强制(又名 "重新制作技巧")一节中有解释.)
这只是抓住作为输入提供的所有内容build!,并将其推入一个enum没有关心它的外观的主体.
如果你试图做一些有意义与变异,那么,你将不得不更加具体谈谈你实际上试图完成的任务,为如何进行最好的建议有所不同似地取决于答案.
| 归档时间: |
|
| 查看次数: |
1874 次 |
| 最近记录: |