如何通过副作用实现变量增量?

时间:2015-06-21 22:21:08

标签: rust side-effects

出于学习目的,我尝试了这个解决方案,但是it does not work

use std::ops::Add;

fn inc<T: Add>(x:&mut T) {
    *x += 1; 
}

fn main() {
    let mut x:i32 = 10;
    let mut y:u8 = 1;
    inc(&mut x);
    inc(&mut y);
    println!("{} {}", x, y);
}

错误讯息:

<anon>:4:5: 4:7 error: binary assignment operation `+=` cannot be applied to types `T` and `_` [E0368]
<anon>:4     *x += 1; 
             ^~
<anon>:4:5: 4:7 help: see the detailed explanation for E0368
error: aborting due to previous error

这样做的正确方法是什么?

1 个答案:

答案 0 :(得分:5)

目前,+=仅在原始整数类型上定义;通常,您需要将其扩展为*x = *x + 1;。这样就会发现更多问题:

<anon>:4:15: 4:16 error: mismatched types:
 expected `T`,
    found `_`
(expected type parameter,
    found integral variable) [E0308]
<anon>:4     *x = *x + 1; 
                       ^
<anon>:4:10: 4:16 error: mismatched types:
 expected `T`,
    found `<T as core::ops::Add>::Output`
(expected type parameter,
    found associated type) [E0308]
<anon>:4     *x = *x + 1; 
                  ^~~~~~
error: aborting due to 2 previous errors

让我们看看Add特征的定义:

pub trait Add<RHS = Self> {
    /// The resulting type after applying the `+` operator
    type Output;

    /// The method for the `+` operator
    fn add(self, rhs: RHS) -> Self::Output;
}

因此Self + RHS会生成<Self as Add<RHS>>::Output类型的对象。

当您将值存储回*x时,计算结果必须为T;因此我们确定T上的界限不需要Add而是Add<???, Output = T>

那么???会是什么? 1的类型是什么?它不是通用的;它是十种已知的原始整数类型之一(isizei8i16i32i64usize,{{1} },u8u16u32)。这显然不起作用,因为整数类型没有实现较小类型的添加 - u64 RHS的默认值(即Self表示T: Add })是您可以依赖的所有内容,但T: Add<Self>不能是1类型。

解决方案是使用生成值 1 的通用函数。 std::num::One中存在一个不稳定,而来自crates.io,T的{​​{1}}包中有一个稳定的。使用前者需要每晚使用Rust,使用后者需要删除num,添加num::One并将std::添加到Cargo.toml依赖项部分。

我们还需要extern crate num;一定允许num Copy工作。

Here’s the final result:

*x