Function std::mem::discriminant
1.21.0 (const: unstable) · source · pub fn discriminant<T>(v: &T) -> Discriminant<T>
Expand description
返回一个唯一标识 v
中的枚举变体的值。
如果 T
不是枚举,则调用此函数不会导致未定义的行为,但返回值是未指定的。
Stability
如果枚举定义改变,则枚举变体的判别式可能会改变。某些变体的判别式在使用相同编译器的编译之间不会改变。 有关更多信息,请参见 Reference。
Examples
这可以用来比较携带数据的枚举,而忽略实际数据:
use std::mem;
enum Foo { A(&'static str), B(i32), C(i32) }
assert_eq!(mem::discriminant(&Foo::A("bar")), mem::discriminant(&Foo::A("baz")));
assert_eq!(mem::discriminant(&Foo::B(1)), mem::discriminant(&Foo::B(2)));
assert_ne!(mem::discriminant(&Foo::B(3)), mem::discriminant(&Foo::C(3)));
Run访问判别式的数值
请注意,从 Discriminant
到原语,到 transmute
是未定义的行为!
如果枚举只有元变体,则可以使用 as
转换访问判别式的数值:
enum Enum {
Foo,
Bar,
Baz,
}
assert_eq!(0, Enum::Foo as isize);
assert_eq!(1, Enum::Bar as isize);
assert_eq!(2, Enum::Baz as isize);
Run如果枚举已选择使用 primitive representation 作为它的判别式,则可以使用指针读取存储判别式的内存位置。 然而,对于使用 default representation 的枚举,不能这样做,因为它没有定义判别式的布局和存储位置 – 它甚至可能根本不存储!
#[repr(u8)]
enum Enum {
Unit,
Tuple(bool),
Struct { a: bool },
}
impl Enum {
fn discriminant(&self) -> u8 {
// SAFETY: 因为 `Self` 被标记为 `repr(u8)`,它的布局是 `repr(C)` 结构体之间的一个 `repr(C)` `union`,每个 `u8` 的判别式作为它的第一个字段,所以我们可以在不偏移指针的情况下读取判别式。
unsafe { *<*const _>::from(self).cast::<u8>() }
}
}
let unit_like = Enum::Unit;
let tuple_like = Enum::Tuple(true);
let struct_like = Enum::Struct { a: false };
assert_eq!(0, unit_like.discriminant());
assert_eq!(1, tuple_like.discriminant());
assert_eq!(2, struct_like.discriminant());
// ⚠️ 这是未定义的行为。不要这样做。⚠️
// assert_eq!(0, unsafe { std::mem::transmute::<_, u8>(std::mem::discriminant(&unit_like)) });
Run