如果我尝试在 Rust 中定义一个递归结构/枚举:
enum Enum {
A,
B(Enum),
C(Enum, i32),
D(Enum, Enum),
...
}
正如预期的那样,我将收到编译错误。
我知道这个问题的一个可能的解决方案是用这样的Box<T>
包装所有递归引用:
enum Enum {
A,
B(Box<Enum>),
C(Box<Enum>, i32),
D(Box<Enum>, Box<Enum>),
...
}
甚至提供type
别名:
type Enum = Box<InnerEnum>;
enum InnerEnum {
A,
B(Enum),
C(Enum, i32),
D(Enum, Enum),
...
}
这让我想知道是否有可能以某种方式自动完成?我有这样的宏吗?
#[boxed]
enum Enum {
A,
B(Enum),
C(Enum, i32),
D(Enum, Enum),
...
}
我强烈建议继续使用显式写出整个枚举的经典方法。
但是 - 关于你的可能性问题 - 我认为可以做到(在一定程度上(:
macro_rules! boxed_enum{
($dummy: ident, enum $E: ident $($variant:tt)* ) => {
pub mod $dummy {
type $E = Box<$dummy>;
pub enum $dummy $($variant)*
}
type $E = $dummy::$dummy;
}
}
boxed_enum!(InnerEnum, enum Enum {
A,
B(Enum),
C(Enum, i32),
D(Enum, Enum),
});
宏采用一个$dummy
,它既是辅助mod
ule 的名称,也是辅助enum
的名称(如您的技巧中所述(,并将虚拟枚举的类型别名为所需的标识符。
我认为可以从$E
生成$dummy
,这样用户就不需要明确指定这一点。但是,这将依赖于concat_idents
(iirc,仅限每晚(或其他板条箱,例如paste
.
如前所述,在这种情况下,我会使用手动解决方案。