Currently I have the following rust function:
fn out_cubic(t: f32, begin: f32, change: f32, duration: f32) -> f32 {
return change * (f32::powf((t / duration) - 1.0, 3.0) + 1.0) + begin;
}
I'm trying to make both begin
and change
parameters generic types. As far I understand, I could use Rust's bounds to say to the compiler that change
and begin
should implement the add and multiply operation:
use std::ops::{Add, Mul};
fn out_cubic<T: Add + Mul>(t: f32, begin: T, change: T, duration: f32) -> T {
return change * (f32::powf((t / duration) - 1.0, 3.0) + 1.0) + begin;
}
But the above code show the following errors:
error[E0308]: mismatched types
--> src/easing.rs:44:21
|
43 | fn out_cubic<T: Add + Mul>(t: f32, begin: T, change: T, duration: f32) -> T {
| - this type parameter
44 | return change * (f32::powf((t / duration) - 1.0, 3.0) + 1.0) + begin;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found `f32`
|
= note: expected type parameter `T`
found type `f32`
error[E0369]: cannot add `T` to `<T as Mul>::Output`
--> src/easing.rs:44:66
|
44 | return change * (f32::powf((t / duration) - 1.0, 3.0) + 1.0) + begin;
| ----------------------------------------------------- ^ ----- T
| |
| <T as Mul>::Output
Which makes sense, the compiler does not have any way to know that the type T
should be able to add and multiply with a f32
type.
My question is, is it possible to create a function that implements both add and multiply operations with T
and f32
types? Something like this:
fn out_cubic<T: Add<T> + Add<f32> + Mul<T> + Mul<f32>>(t: f32, begin: T, change: T, duration: f32) -> T {
return change * (f32::powf((t / duration) - 1.0, 3.0) + 1.0) + begin;
}
Since you're adding f32 + T
, you actually need to assert that f32
is Add<T>
:
fn out_cubic<T>(t: f32, begin: T, change: T, duration: f32) -> T
where
T: Add<T, Output = T> + Mul<f32, Output = T>, // assert that Output is T
f32: Add<T> + Add, // the `+ Add` is necessary for f32 to f32 addition for whatever reason
{
return change * (f32::powf((t / duration) - 1.0, 3.0) + 1.0) + begin;
}
You could of course, make it even more generic by only asserting that it has to operate on their outputs, but it starts ot get messy:
fn out_cubic<T>(t: f32, begin: T, change: T, duration: f32) -> <<T as Mul<f32>>::Output as Add<T>>::Output
where
T: Mul<f32>,
<T as Mul<f32>>::Output: Add<T>,
f32: Add<T> + Add,
{
return change * (f32::powf((t / duration) - 1.0, 3.0) + 1.0) + begin;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With