推广添加无符号和有符号整数类型

时间:2018-06-05 08:40:06

标签: rust integer

我想要一个Rust功能,允许u32u64u128)类型添加到i32i64,{{1检查溢出时输入。

我的实施:

i128

我有另一个类似的/// Add u32 to i32. In case of an overflow, return None. fn checked_add_i32_u32(a: i32, b: u32) -> Option<i32> { let b_half = (b / 2) as i32; let b_rem = (b % 2) as i32; Some(a.checked_add(b_half)?.checked_add(b_half)? .checked_add(b_rem)?) } /// Add u64 to i64. In case of an overflow, return None. fn checked_add_i64_u64(a: i64, b: u64) -> Option<i64> { let b_half = (b / 2) as i64; let b_rem = (b % 2) as i64; Some(a.checked_add(b_half)?.checked_add(b_half)? .checked_add(b_rem)?) } u128。我觉得我在重复自己。我对这些功能的测试看起来非常相似。

有没有办法可以重构我的代码并只改为一个函数?我不确定如何概括i128u32(或i32u64i64u128)之间的关系。< / p>

1 个答案:

答案 0 :(得分:6)

您可以使用宏:

trait CustomAdd: Copy {
    type Unsigned;

    fn my_checked_add(self, b: Self::Unsigned) -> Option<Self>;
}

macro_rules! impl_custom_add {
    ( $i:ty, $u:ty ) => {
        impl CustomAdd for $i {
            type Unsigned = $u;

            fn my_checked_add(self, b: $u) -> Option<$i> {
                let b_half = (b / 2) as $i;
                let b_rem = (b % 2) as $i;

                Some(self.checked_add(b_half)?.checked_add(b_half)?
                    .checked_add(b_rem)?)
            }
        }
    }
}

impl_custom_add!(i32, u32);
impl_custom_add!(i64, u64);
// etc.

#[test]
fn tests() {
    assert_eq!(123.my_checked_add(10_u32), Some(133));
}