我决定实现一个使用几个标志的协议,所以我开始enum为标志定义s.然而,当我想定义有两个值可以是一个标志true或者false我得到一个错误信息:
// The protocol definition says that the flag
// can have two values true or false, so I could just use
// plain bool, but I want another name for true and false.
enum Flag {
ONE = true,
TWO = false,
}
Run Code Online (Sandbox Code Playgroud)
error[E0308]: mismatched types
--> src/lib.rs:5:11
|
5 | ONE = true,
| ^^^^ expected isize, found bool
error[E0308]: mismatched types
--> src/lib.rs:6:11
|
6 | TWO = false,
| ^^^^^ expected isize, found bool
Run Code Online (Sandbox Code Playgroud)
我想使用枚举而不是两个常量的原因是该标志不是bool.它是表示值为true或false的标志,但我不想混合正常bools和标志.如果我使用了bool常量,我可以将标志值传递给每个带有boolas参数的函数,或者在表达式中使用它们bool,例如
if ONE {
}
fn some_function_with_a_flag(b: bool);
// I don't want this!
some_function_with_a_flag(ONE);
Run Code Online (Sandbox Code Playgroud)
当使用标志作为结构成员时,使用枚举而不是布尔常量也可以防止更多错误.有更多的标志以相同的方式定义,所以当我只使用普通的bools和常量时,我会有一个类似的结构
struct Header {
flag1: bool,
flag2: bool,
flag3: bool,
}
Run Code Online (Sandbox Code Playgroud)
编译器将接受切换标志值的代码:
h = Header { flag3: ONE, flag1: TWO, flag2: ONE };
Run Code Online (Sandbox Code Playgroud)
当每个标志都是它自己的类型(别名bool)时,这是不可能的.
定义与值枚举的点true和false只是该协议定义了这种方式.在我的代码中,我可能只在数据打包被序列化时使用标志的布尔值(它是数据头的一部分).
好的,编译器总是假设底层类型是isize.它可以从值中推导出来,但让我们来定义它
#[repr(bool)]
enum E1 {
ONE = true,
TWO = false,
}
Run Code Online (Sandbox Code Playgroud)
error[E0552]: unrecognized representation hint
--> src/lib.rs:1:8
|
1 | #[repr(bool)]
| ^^^^
Run Code Online (Sandbox Code Playgroud)
看起来我必须使用u8底层类型,然后始终将值转换为bool
#[repr(u8)]
enum E2 {
ONE = 1,
TWO = 0,
}
let x = E2::ONE as bool;
Run Code Online (Sandbox Code Playgroud)
这编译,但似乎过于复杂.有没有更好的方式来定义enum与bool价值?bool我可以指定值的类型别名是否有成语?我可以这样做
enum Flag {
TWO,
ONE,
}
Run Code Online (Sandbox Code Playgroud)
但现在我必须再次将值转换为值bool,并且定义的顺序看起来不自然.
由于bool值只会在读/写头时使用,我只需将转换放入相应的函数中,并保持程序的其余部分不受实现细节的影响.
不,你不能使用a bool作为枚举的底层表示.
相反,创建常量:
const ONE: bool = true;
const TWO: bool = false;
Run Code Online (Sandbox Code Playgroud)
您还可以实现一个将枚举转换为布尔值的方法:
enum Flag {
One,
Two,
}
impl From<Flag> for bool {
fn from(f: Flag) -> bool {
match f {
Flag::One => true,
Flag::Two => false,
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,惯用的Rust样式UpperCamelCase用于枚举变体和SHOUTING_SNAKE_CASE常量.
我同意评论者的意见,想要将枚举用作布尔值是很奇怪的.您可以比较枚举是否相等或匹配:
if let Flag::One = flag {
println!("something");
} else {
println!("something else");
}
Run Code Online (Sandbox Code Playgroud)
match flag {
Flag::One => println!("something"),
Flag::Two => println!("something else"),
}
Run Code Online (Sandbox Code Playgroud)
如果您担心大小使用,请注意没有成员的双值枚举(最多256个值枚举)与布尔值的大小相同:
enum Flag {
One,
Two,
}
fn main() {
use std::mem;
assert_eq!(mem::size_of::<Flag>(), mem::size_of::<bool>());
}
Run Code Online (Sandbox Code Playgroud)
也可以看看:
| 归档时间: |
|
| 查看次数: |
576 次 |
| 最近记录: |