For learning purposes, I tried this solution, but 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);
}
Error message:
<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
What is the right way to do that?
At present,
+=
is only defined on the primitive integer types; generically, you will need to expand it to*x = *x + 1;
instead. This then reveals more problems:Let’s look at the
Add
trait’s definition:So
Self + RHS
produces an object of type<Self as Add<RHS>>::Output
.As you’re storing the value back in
*x
, the result of the calculation must be aT
; thus we establish that the bound onT
will need to be notAdd
butAdd<???, Output = T>
.What, then, will
???
be? What is the type of1
? It’s not generic; it’s one of the ten known primitive integer types (isize
,i8
,i16
,i32
,i64
,usize
,u8
,u16
,u32
,u64
). This clearly won’t work, because the integral types don’t implement addition of lesser types—the default value forRHS
ofSelf
(that is, whereT: Add
meansT: Add<Self>
) is all you can count on, but1
cannot be of typeT
.The solution is to use a generic function that produces the value 1. There is one unstable in
std::num::One
, and a stable one in thenum
crate from crates.io,num::One
. Using the former requires the Rust nightly, using the latter requires dropping thestd::
, adding anextern crate num;
and addingnum
to your Cargo.toml dependencies section.We also need a
Copy
bound to allow the*x
of*x + 1
to work.Here’s the final result: