何时使用零变体枚举而不是类似单元的结构体

5
如果我理解正确,Rust中的类单元结构体可以像Erlang中的原子一样使用。
但是我不明白零变量枚举提供了什么。有人能解释一下零变量枚举的主要目的以及在哪些情况下它们可能优于类单元结构体吗?

1
它们被使用的原因是因为没有变体的枚举无法构建,但没有字段的结构体可以。 - Locke
1
单元类型 () 有一个单一的值。该类型的所有值都相同。零变体枚举根本没有值。 - Sven Marnach
1
这就是我不理解的地方。一个无法构造或拥有值的类型有什么用处? - ITChap
1个回答

3

零变体枚举的一个用法是表示无法到达的代码。例如,一个不会失败的TryFromFromStr。这通常在使用泛型时发生。以下是一个示例:OnceCell同时具有get_or_init()get_or_try_init()方法。

enum Void {}
match self.get_or_try_init(|| Ok::<T, Void>(f())) {
    Ok(val) => val,
    Err(void) => match void {},
}


为了避免代码重复,the get_or_init()方法调用了get_or_try_init()。然而,如果get_or_try_init()调用没有内联,那么在运行时会因为不可能的Err情况而产生开销和panic。一旦稳定下来,这将被never类型所取代。使用空枚举相比于单元结构体有两个优点:
  1. 它们不能被错误地构造。
  2. 它们可以提示优化器该代码是无法到达的,并允许其删除该代码。它们还可以帮助开发人员避免代码中的panic,因为一个不会失败的枚举可以通过match value {}转换为never类型,而never类型可以被强制转换为任何其他类型。以上述once_cell代码为例。
另一个用法是在泛型中,当你只需要类型而不需要值时,例如在编译时的策略模式中,有些人更喜欢使用零变体枚举来表示这些类型不应该被实例化。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接