有没有办法创建枚举值的别名?
Is there a way to create an alias of an enum value?
有没有办法做这样的事情?
enum MyType {
Left,
Right,
#[cfg(universe = "normal")]
Port = Left,
#[cfg(universe = "normal")]
Starboard = Right,
#[cfg(universe = "mirror")]
Port = Right,
#[cfg(universe = "mirror")]
Starboard = Left,
}
如果你真的尝试了,你会得到这个错误(我不得不添加 MyType::
):
error[E0080]: constant evaluation error
--> <anon>:9:12
|
9 | Port = MyType::Left,
| ^^^^^^^^^^^^ unimplemented constant expression: enum variants
Here 是触发该错误的地方。
您的实施没有任何意义。看一个更简单的版本:
enum MyType {
One,
Two = One,
}
换句话说:
enum MyType {
One = 1,
Two = 1,
}
您要求编译器创建两个相同的枚举变体,但枚举的全部意义在于它们 互斥。
相反,创建一个常量(关联或其他方式):
enum MyType {
One,
}
const TWO: MyType = MyType::One;
据我所知还没有。
Rust 中的枚举不像在 C 中那样 "bundle of constant values"。支持将数值与常量相关联,但仅此而已。当然,您可以创建任何名称的常量,但它们不允许您对枚举值进行模式匹配。
在某种意义上,枚举变体的别名有点像类型字段的别名。我从未见过任何由两个名称标识的字段出现;不知道有没有语言支持
我建议的解决方案是硬着头皮创建两个单独的枚举,并在它们之间进行转换:
use std::convert::From;
enum Side {
Left,
Right,
}
enum PortSide {
Port,
Starboard,
}
#[cfg(not(universe = "mirror"))]
impl From<Side> for PortSide {
fn from(s: Side) -> PortSide {
match s {
Side::Left => PortSide::Port,
Side::Right => PortSide::Starboard,
}
}
}
#[cfg(universe = "mirror")]
impl From<Side> for PortSide {
fn from(s: Side) -> PortSide {
match s {
Side::Left => PortSide::Starboard,
Side::Right => PortSide::Port,
}
}
}
此外,我建议您不要要求指定某个功能,而是在没有此功能的情况下允许默认行为。在您的情况下,"normal" 似乎应该是默认行为。
您可以使用关联常量来获得看起来与枚举变体非常相似的常量:
#[derive(PartialEq, Eq)]
pub enum X {
A,
B,
}
impl X {
pub const A1: X = X::A;
}
关联的常量在枚举内部命名空间,就像普通变体一样。它与模式匹配兼容——即使是无法到达的警告和详尽的匹配规则也能正常工作。
match x {
X::A1 => ...,
X::B => ...,
}
存在一些限制:最重要的是您不能拥有与该值关联的任何数据。您还需要 #[derive(PartialEq, Eq)]
在您的结构上。
有没有办法做这样的事情?
enum MyType {
Left,
Right,
#[cfg(universe = "normal")]
Port = Left,
#[cfg(universe = "normal")]
Starboard = Right,
#[cfg(universe = "mirror")]
Port = Right,
#[cfg(universe = "mirror")]
Starboard = Left,
}
如果你真的尝试了,你会得到这个错误(我不得不添加 MyType::
):
error[E0080]: constant evaluation error
--> <anon>:9:12
|
9 | Port = MyType::Left,
| ^^^^^^^^^^^^ unimplemented constant expression: enum variants
Here 是触发该错误的地方。
您的实施没有任何意义。看一个更简单的版本:
enum MyType {
One,
Two = One,
}
换句话说:
enum MyType {
One = 1,
Two = 1,
}
您要求编译器创建两个相同的枚举变体,但枚举的全部意义在于它们 互斥。
相反,创建一个常量(关联或其他方式):
enum MyType {
One,
}
const TWO: MyType = MyType::One;
据我所知还没有。
Rust 中的枚举不像在 C 中那样 "bundle of constant values"。支持将数值与常量相关联,但仅此而已。当然,您可以创建任何名称的常量,但它们不允许您对枚举值进行模式匹配。
在某种意义上,枚举变体的别名有点像类型字段的别名。我从未见过任何由两个名称标识的字段出现;不知道有没有语言支持
我建议的解决方案是硬着头皮创建两个单独的枚举,并在它们之间进行转换:
use std::convert::From;
enum Side {
Left,
Right,
}
enum PortSide {
Port,
Starboard,
}
#[cfg(not(universe = "mirror"))]
impl From<Side> for PortSide {
fn from(s: Side) -> PortSide {
match s {
Side::Left => PortSide::Port,
Side::Right => PortSide::Starboard,
}
}
}
#[cfg(universe = "mirror")]
impl From<Side> for PortSide {
fn from(s: Side) -> PortSide {
match s {
Side::Left => PortSide::Starboard,
Side::Right => PortSide::Port,
}
}
}
此外,我建议您不要要求指定某个功能,而是在没有此功能的情况下允许默认行为。在您的情况下,"normal" 似乎应该是默认行为。
您可以使用关联常量来获得看起来与枚举变体非常相似的常量:
#[derive(PartialEq, Eq)]
pub enum X {
A,
B,
}
impl X {
pub const A1: X = X::A;
}
关联的常量在枚举内部命名空间,就像普通变体一样。它与模式匹配兼容——即使是无法到达的警告和详尽的匹配规则也能正常工作。
match x {
X::A1 => ...,
X::B => ...,
}
存在一些限制:最重要的是您不能拥有与该值关联的任何数据。您还需要 #[derive(PartialEq, Eq)]
在您的结构上。