Generics that use operators - how to express bounds?

pub fn lerp<T: std::ops::Mul<T> + std::ops::Add<T>>(a: T, b: T, val: f32) -> T {
    let safeval = clamp(val, 0.0, 1.0); 
    a * (1.0 - safeval) + b * safeval // interpolate
}

Simple linear interpolation. I'd like this to work for any type that implements

Mul for T * f32 -> T
Add for T + T -> T.

The above code produces:

|         ^^^^^^^^^^^^^^^ expected type parameter `T`, found `f32`
|
= note: expected type parameter `T`
                     found type `f32`

which is reasonable. I'm doing a mixed-mode multiply. But how do I tell Rust that? I can't find the syntax for that. I tried forms like

Mul<T,f32,Output=T>

but I just get an error telling me that only one type is expected.

I have types of my own that implement multiply by scalar, as below, so I want a generic function that will work on all of them, plus the built-in f32.

/// Multiply by scalar on right
impl ops::Mul<f32> for Vector3 {
    type Output = Vector3;
    fn mul(self, rhs: f32) -> Vector3 {
        LLVector3 {
            x: self.x * rhs,
            y: self.y * rhs,
            z: self.z * rhs,
        }
    }
}

The bounds for this are:

T: Mul<f32, Output=T>,
T: Add<T, Output=T>

Combined into a single clause, that's:

T: Mul<f32, Output=T> + Add<T, Output=T>
3 Likes

In general, T: Op<U, Output = V> means, that T op U has type V (where op is an operator corresponding to the chosen trait). I.e.:

  • type which implements trait is the LHS of operator;
  • type parameter is the RHS (by default it is equal to LHS);
  • associated type is the result.

So that's the syntax when you need to express 3 types for an operator.

Got it working for my vector types. Thanks.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.