rust - 有没有办法将布尔值用作枚举的基础类型?
问题描述
我决定实现一个使用几个标志的协议,所以我开始为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,
}
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
我想使用枚举而不是两个常量的原因是标志不是布尔值。它是表示值为真或假的标志,但我不想混合正常bool
的s和标志。如果我使用bool
常量,我可以将标志值传递给每个接受 abool
作为参数的函数,或者在表达式中使用它们 as bool
,例如
if ONE {
}
fn some_function_with_a_flag(b: bool);
// I don't want this!
some_function_with_a_flag(ONE);
当使用标志作为结构成员时,使用枚举而不是布尔常量还可以防止更多错误。以相同的方式定义了更多的标志,所以当我只使用普通bool
的 s 和常量时,我会有一个类似的结构
struct Header {
flag1: bool,
flag2: bool,
flag3: bool,
}
编译器将接受切换标志值的代码:
h = Header { flag3: ONE, flag1: TWO, flag2: ONE };
bool
当每个标志都是它自己的类型(别名为)时,这是不可能的。
用值定义枚举的意义true
在于false
协议以这种方式定义它。在我的代码中,我可能只会在数据被打包以进行序列化时使用标志的布尔值(它是数据头的一部分)。
好的,编译器总是假定底层类型是isize
. 它可以从值中派生出来,但让我们定义它
#[repr(bool)]
enum E1 {
ONE = true,
TWO = false,
}
error[E0552]: unrecognized representation hint
--> src/lib.rs:1:8
|
1 | #[repr(bool)]
| ^^^^
看起来我必须使用u8
作为基础类型,然后总是将值转换为bool
#[repr(u8)]
enum E2 {
ONE = 1,
TWO = 0,
}
let x = E2::ONE as bool;
这可以编译,但似乎过于复杂。有没有更好的方法来定义一个enum
withbool
值?我可以在其中指定值的类型别名是否有成语bool
?我可以做
enum Flag {
TWO,
ONE,
}
但现在我又不得不一直将值转换bool
为,定义的顺序看起来不自然。
由于 bool 值仅在读取/写入标头时使用,因此我只需将转换放入相应的函数中,并使程序的其余部分不受实现细节的影响。
解决方案
不,您不能使用 abool
作为枚举的基础表示。
相反,创建常量:
const ONE: bool = true;
const TWO: bool = false;
您还可以实现将枚举转换为布尔值的方法:
enum Flag {
One,
Two,
}
impl From<Flag> for bool {
fn from(f: Flag) -> bool {
match f {
Flag::One => true,
Flag::Two => false,
}
}
}
请注意,惯用的 Rust 风格UpperCamelCase
用于枚举变体和SHOUTING_SNAKE_CASE
常量。
我同意评论者的观点,即想将枚举用作布尔值很奇怪。您可以比较枚举是否相等或匹配它们:
if let Flag::One = flag {
println!("something");
} else {
println!("something else");
}
match flag {
Flag::One => println!("something"),
Flag::Two => println!("something else"),
}
如果您担心大小的使用,请注意没有成员的二值枚举(最多 256 个值的枚举)与布尔值的大小相同:
enum Flag {
One,
Two,
}
fn main() {
use std::mem;
assert_eq!(mem::size_of::<Flag>(), mem::size_of::<bool>());
}
也可以看看:
推荐阅读
- php - 如何将.env文件中的环境变量分配给$_ENV变量php
- powershell - 管道数组变量(经典)导致powershell异常
- facebook - 如何深入了解 Facebook 页面关注者 + 具有成本效益的自动化数字营销软件解决方案
- javascript - MongoDb 更新参考
- html - 具有绝对位置的元素内的大文本不会随其容器增长
- javascript - 为什么 CKEditor 为我的自定义标签添加空项目符号?
- database - Flask 存储和统计视图的数量
- r - R:创建反映字典和df中列之间匹配的类别列
- python - python弹出列表会触发要更新列表的另一个副本?
- scala - Spark Scala - 编译错误