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
Addtrait’s definition:So
Self + RHSproduces 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 onTwill need to be notAddbutAdd<???, 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 forRHSofSelf(that is, whereT: AddmeansT: Add<Self>) is all you can count on, but1cannot 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 thenumcrate from crates.io,num::One. Using the former requires the Rust nightly, using the latter requires dropping thestd::, adding anextern crate num;and addingnumto your Cargo.toml dependencies section.We also need a
Copybound to allow the*xof*x + 1to work.Here’s the final result: