首页 > 解决方案 > 具有多种类型的边界

问题描述

目前我有以下防锈功能:

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;
}

我正在尝试同时创建beginchange参数泛型类型。据我了解,我可以使用 Rust 的边界对编译器说change并且begin应该实现加法和乘法操作:

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;
}

但上面的代码显示以下错误:

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

这是有道理的,编译器没有任何方法知道该类型T应该能够与f32类型相加和相乘。

我的问题是,是否可以创建一个函数来实现加法和乘法运算T以及f32类型?像这样的东西:

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;
}

标签: genericsrust

解决方案


由于您要添加,因此您实际上f32 + T需要断言:f32Add<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;
}

当然,您可以通过仅断言它必须对其输出进行操作来使其更加通用,但它开始变得混乱:

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;
}

推荐阅读