将i8添加到i8的惯用方法

时间:2015-08-20 06:52:01

标签: rust

请考虑以下代码:

let mut val : u8 = 125;
let deltas : [i8; 4] = [5, -5, 5, 5];

let delta = select_current_delta(deltas);

val += delta;

这看起来很简单。我想根据某些标准增加或减少字节值(我有办法防止u8值溢出。)

当然,这不会编译:

 > rustc lala.rs
 lala.rs:7:12: 7:17 error: mismatched types:
  expected `u8`,
     found `i8`
 (expected u8,
     found i8) [E0308]
 lala.rs:7     val += delta;
                      ^~~~~

咄!在Rust中,似乎禁止混合使用有符号和无符号类型。怎么样?

val = (val as i8 + delta) as u8;

这会编译,但是当我尝试运行它时......

> ./lala
thread '<main>' panicked at 'arithmetic operation overflowed', lala.rs:7

是的,i8的最大值是125,加上5会溢出,即使u8的值非常好。

我能够找到两种有效的解决方案:

val = (val as i16 + delta as i16) as u8;
// or
if delta < 0 { val -= (-delta) as u8 }
else { val += delta as u8}

这些似乎都不优雅。是否有一种惯用的方式将u8添加到i8?

2 个答案:

答案 0 :(得分:7)

您可以这样做以避免溢出并包装添加:

val = (val as i8).wrapping_add(delta) as u8;

Look here for all the arithmetic operations

答案 1 :(得分:7)

  

是否有惯用的方式将u8添加到i8

u8i8)添加+的问题是:结果应该是什么类型? u8i8都不是更好,使用i16虽然正确但可能会令人惊讶。

因此,目前,不支持混合积分操作数。惯用的方法是将两个操作数转换为公共类型,这也是结果的类型。这已经是你正在做的事情。

  

但是,u8 += i8是什么?

不幸的是,目前,这是u8 = u8 + i8的糖,因此具有+的所有限制,即使结果类型不是问题。

由于Rust的所有恼人的限制,它有一个RFC!这是PR #953: Overloaded Assignment Operations。此RFC处于最终评论期,因此很快就会做出决定,希望这意味着它将被接受,Rust将获得对混合积分分配操作的支持。

作为个人偏好,现在,我会选择:

val = (val as i16 + delta as i16) as u8;

避免了分支。