如果我尝试在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
的名称(如您的技巧中所述),并且将虚拟枚举类型化为所需的标识符。 >
我认为可以从$dummy
生成$E
,因此用户无需明确指定。但是,这将依赖于concat_idents
(iirc,仅每晚)或其他板条箱,例如paste
。
如上所述,在这种情况下,我将采用手动解决方案。