rust 与NonZeroU8等效,但使用u8::MAX?代替0,

doinxwow  于 2022-12-19  发布在  其他
关注(0)|答案(2)|浏览(131)

我希望能够将Option<NonZeroU8>用于其紧凑的repr,但仍然能够使用0。
有没有办法用u8::MAX代替0作为不可表示的值?

qnzebej0

qnzebej01#

要真正直接获得利基优化,您必须使用超级不稳定的rustc_属性。

#![feature(rustc_attrs)]

#[rustc_layout_scalar_valid_range_start(0)]
#[rustc_layout_scalar_valid_range_end(254)]
struct NonMaxU8(u8);

fn main() {
    dbg!(std::mem::size_of::<Option<NonMaxU8>>());
}
[src/main.rs:8] std::mem::size_of::<Option<NonMaxU8>>() = 1

我说"超级不稳定"是因为这些属性永远不会稳定,至少在它们当前的形式下不会。如果不使用feature(rustc_attrs),将发出以下消息:

error[E0658]: the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable niche optimizations in libcore and libstd and will never be stable
 --> src/main.rs:3:1
  |
3 | #[rustc_layout_scalar_valid_range_start(0)]
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable

error[E0658]: the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable niche optimizations in libcore and libstd and will never be stable
 --> src/main.rs:4:1
  |
4 | #[rustc_layout_scalar_valid_range_end(254)]
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable

已经有人要求编译器支持范围整数,比如讨论here,但我不认为到目前为止已经正式提出了任何建议。

ozxc1zmp

ozxc1zmp2#

有一个nonmax机箱提供了这个功能,具体请参见NonMaxU8。这个功能之所以有效,是因为它在内部使用NonZeroU8,并在创建和.get()方法时进行适当的转换。
如果你想要一个不同的变量,而不仅仅是zero或max,你可以很容易地自己创建。nonmax crate使用XOR策略将不可表示的值清零,或者使用模运算方法,如注解中所建议的:

pub struct NonTenU8(NonZeroU8);

impl NonTenU8 {
    const UNREPRESENTABLE: u8 = 10;

    /// Creates a u8 value that cannot be ten.
    pub fn new(value: u8) -> Option<Self> {
        NonZeroU8::new(value ^ Self::UNREPRESENTABLE).map(Self)
        // NonZeroU8::new(value.wrapping_sub(Self::UNREPRESENTABLE)).map(Self)
    }

    pub fn get(&self) -> u8 {
        self.0.get() ^ Self::UNREPRESENTABLE
        // self.0.get().wrapping_add(Self::UNREPRESENTABLE)
    }
}

相关问题