有没有办法创建枚举值的别名?

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 => ...,
}

playground

存在一些限制:最重要的是您不能拥有与该值关联的任何数据。您还需要 #[derive(PartialEq, Eq)] 在您的结构上。