I have struct defined like this
struct Shape<T> {
line_one: T,
line_two: T,
}
I am trying to create a simple trait and implementation that takes this struct to calculate some simple math.
My trait and impls look like this
trait Calculate<T: Mul<Output = T>> {
fn calc(&self, Shape: T) -> T;
}
impl<T> Calculate<T> for Shape<T> {
fn calc(&self, Shape: T) -> T {
self.line_one * 2 + self.line_two * 2
}
}
impl Calculate<i32> {
fn calc(&self) -> i32 {
self.line_one * 2 + self.line_two * 2
}
}
fn calc_fn<T: Calculate<i32>>(calculate: T) {
calculate.calc();
}
When I put this into the Rust playground, the compile fails as Mul
is not implemented in the impl Calculate<T>
. However, if I change <T>
to <T: Mul<Output = T>>
, I get the error that
<anon>:14:21: 14:22 error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `:`
<anon>:14 impl <T> Calculate<T: Mul<Output = T>> for Shape<T>
I'm at a loss as how to implement Mul
for T
in impl Calculate<T>
.
What I'm trying to achieve is code that I can send either a f32
or i32
in without needing to create two different impl definitions so can just pass in T
.
This syntax is incorrect:
you want
I'd almost always recommend using
where
clause instead; I think it reads better and might have helped prevent this case:This just unlocks more errors. You are trying to multiply by
2
, an integral variable that hasn't been fully nailed down yet — is it au8
? is it ani32
? The restrictions don't say thatT
can be multiplied by a2
. Additionally, you try to add values together, but there's no guarantee that you can add the typeT
.The
impl Calculate<i32>
andcalc_fn
blocks don't really make sense; it's unlikely you want to implement functions for the trait and you don't supply aShape
in the latter. The trait also doesn't use theShape: T
parameter (and Rust usessnake_case
variable names anyway).In this case, it'd probably be way easier:
Note that these are not equivalent! The
f64
has floating point literals (2.0
) not integral (2
).If you must have a generic, you are going to need to convert the literal
2
to the typeT
or add a restriction that T can be multiplied by some known size. Unfortunately,f64
cannot by multiplied by any integral value without casting.The
FromPrimitive
trait from the num crate is key here. Making the typesCopy
also makes the implementation easier.