【发布时间】:2019-03-03 21:14:11
【问题描述】:
我决定实现一个使用几个标志的协议,所以我开始为标志定义enums。但是,当我想定义一个具有两个值的标志时,可以是 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
我想使用枚举而不是两个常量的原因是标志不是布尔值。它是表示值为真或假的标志,但我不想将普通的bools 和标志混合在一起。如果我使用bool 常量,我可以将标志值传递给每个以bool 作为参数的函数,或者在表达式中使用它们作为bool,例如
if ONE {
}
fn some_function_with_a_flag(b: bool);
// I don't want this!
some_function_with_a_flag(ONE);
在使用标志作为结构成员时,使用枚举而不是布尔常量还可以防止更多错误。以同样的方式定义了更多的标志,所以当我只使用普通的bools 和常量时,我会有一个类似
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;
这可以编译,但似乎过于复杂。有没有更好的方法来定义具有bool 值的enum? bool 的类型别名是否有一个习惯用法,我可以在其中指定值?我可以这样做
enum Flag {
TWO,
ONE,
}
但现在我又不得不一直将值转换为bool,并且定义的顺序看起来不自然。
由于 bool 值只会在读/写 header 时使用,所以我将把转换放入相应的函数中,并让程序的其余部分不受实现细节的影响。
【问题讨论】:
-
既然要转换为布尔值,那么不使用布尔值的原因是什么?
-
“但现在我又不得不一直将值转换为 bool”,这就是 Rust 枚举的工作方式,它与布尔值无关:play.rust-lang.org/…
-
你能解释一下为什么你想要一个不是 bool 的枚举,却像 bool 一样使用它吗?
-
您无需指定
#[repr(u8)]即可将您的枚举表示为单个字节;如果判别式在界限内,无论判别式是显式的还是隐式的,编译器都已经这样做了。 -
这两个语句似乎不一致:“我想使用枚举而不是两个常量的原因是标志不是枚举,我不想混合普通布尔值和旗帜。”和“看起来我必须使用
u8作为基础类型,然后总是将值转换为bool[...] 这可以编译,但似乎过于复杂。”您是否希望能够将bool分配给Flag?如果将as bool置入“过于复杂”,那么您如何才能将其删除而不会意外混合Flags 和bools?
标签: rust