我发现自己经常定义如下的enum
类型:
struct Foo { }
struct Bar { }
struct Baz { }
enum MyEnum {
Foo(Foo),
Bar(Bar),
Baz(Baz),
}
我发现Foo(Foo)
的重复既优雅又多余。它还使初始化变得多余:
let example = MyEnum::Foo(Foo{ /* ... */ });
我想改写类似以下的伪代码:
struct Foo { }
struct Bar { }
struct Baz { }
type_enum MyEnum {
Foo,
Bar,
Baz,
}
let example = MyEnum::Foo{ /* ...anything that `Foo` supports ... */ };
以上内容与C ++ 17中的std::variant
非常相似。 Rust支持类似的功能吗?
答案 0 :(得分:3)
enum
的变体可以是struct,tuple或unit struct。因此,您可以简单地定义:
enum MyEnum {
Foo {},
Bar {},
Baz {},
}
或者,如果您想将这些变体定义为独立的结构本身,我认为更惯用的“功能”方式是使用类似Either
的方式:
enum Either<L, R> {
Left(L),
Right(R),
}
struct Foo {}
struct Bar {}
type MyEnum = Either<Foo, Bar>;
有一个同名的箱子,但是这个基本定义在大多数情况下应该足够了。
答案 1 :(得分:3)
也许您可以使用这种基于宏的解决方案:
macro_rules! type_dispatch_enum{(enum $e: ident {$($v: ident,)*}) => {
enum $e {
$($v($v),)*
}
$(
impl From<$v> for $e {
fn from(v: $v) -> Self {
$e::$v(v)
}
}
)+
}}
struct S1 {}
struct S2;
struct S3(usize);
type_dispatch_enum!(enum E {
S1,
S2,
S3,
});
fn take_e(e: E) {}
fn main() {
take_e(S1{}.into());
take_e(S2.into());
take_e(S3(5).into());
}