rust - Rust 泛型上的类型参数不匹配错误

标签 rust

预期类型参数T,发现类型参数A错误显示。我也编写了生命周期实现代码,但它仍然不能解决问题。我做错了什么?

fn main() {
    let x = 3;
    let y = 5.0;
    let max_value = max(x, y);
    println!("The maximum value is {}", max_value); 
}

fn max<T: PartialOrd, A: PartialOrd>(x: T, y: A) -> T {
    if x > y {
        x
    } else {
        y
    }
}

// fn main() {
//     let x = 3;
//     let y = 5.0;
//     let max_value = max(&x, &y);
//     println!("The maximum value is {}", max_value); 
// }

// fn max<'a, T: PartialOrd + Copy, A: PartialOrd + Copy>(x: &'a T, y: &'a A) -> &'a T {
//     if x > y {
//         x
//     } else {
//         y
//     }
// }

最佳答案

TA不必是同一类型,所以你有两个问题。

第一个是你约束 TA成为PartialOrd ,与 PartialOrd<Self> 相同。所以你的实际约束是 T: PartialOrd<T>, A: PartialOrd<A> 。这意味着您可以比较 T 的顺序发送至其他 T的和A发送至其他 A的,但是x > y比较 TA .

相反,您需要约束 T: PartialOrd<A> 。 (这也失败了,但是因为main()中的调用——稍后会详细介绍。)

其次,该函数声明返回 T但是else区 block 返回y ,这不是 T 。 Rust 是静态类型的,因此它期望类型完全匹配。

可以通过要求 A 来解决此问题可以转换为T (即 A: Into<T> )然后您可以返回 y.into()来自else block 。

所以此时,我们有:

fn main() {
    let x = 3;
    let y = 5.0;
    let max_value = max(x, y);
    println!("The maximum value is {}", max_value); 
}

fn max<T: PartialOrd<A>, A: Into<T>>(x: T, y: A) -> T {
    if x > y {
        x
    } else {
        y.into()
    }
}

但现在你还有更多问题:

  • 没有类型 TA满意T: PartialOrd<A>哪里T是一个整数且 A是一个 float ,因此您不能使用 3 调用此函数和5.0就像你在 main() 中所做的那样.
  • 同样,Into<T> 也没有实现上A对于整数类型 T和浮点类型 A .
  • x > y移动 xy ,之后您将无法归还它们。通过限制 T 可以轻松解决这个问题。和A成为Copy .

第二个问题可以通过使用一个表示“TA”的枚举并返回它来解决。 either crate has such a type called Either ,我们可以在这里使用 Either<T, A> :

use either::Either;

fn main() {
    let x = 3;
    let y = 5.0;
    let max_value = max(x, y);
    println!("The maximum value is {}", max_value); 
}

fn max<T: PartialOrd<A> + Copy, A: Copy>(x: T, y: A) -> Either<T, A> {
    if x > y {
        Either::Left(x)
    } else {
        Either::Right(y)
    }
}

(println! 之所以有效,是因为当 Either<T, A>Display 都实现时,T 实现了 A。)

您仍然面临整数和 float 之间没有内置排序实现的问题。

“万岁玛丽”解决方案可能是要求 TA都可以转换为f64然后转换xyf64在比较它们之前:

use either::Either;

fn main() {
    let x = 3;
    let y = 5.0;
    let max_value = max(x, y);
    println!("The maximum value is {}", max_value); 
}

fn max<T: Copy + Into<f64>, A: Copy + Into<f64>>(x: T, y: A) -> Either<T, A> {
    if x.into() > y.into() {
        Either::Left(x)
    } else {
        Either::Right(y)
    }
}

这是我们实际编译的第一段代码,这可能足以满足您的目的。然而,仍然存在一些问题:

  • i64u64 无法无损转换为f64 ,因此他们不实现 Into<f64> ,所以如果你改变 let x = 3;let x = 3u64; (或 3i64 )编译将再次失败。
  • f64不实现Ord因为可能有两个 f64xy不相等,但都不大于另一个——如果任一值为 NaN , 例如。这不会导致您的程序崩溃,但可能会产生意外或不正确的结果。

我怀疑这是一个学习练习,所以希望这个答案可以帮助您理解原始代码有什么问题。我不会推荐在现实世界的程序中使用这样的函数;相反,最好将两个参数转换为相同的 Ord -提前实现类型,然后你可以使用内置的 std::cmp::max 函数(或 Ord::max )。

关于rust - Rust 泛型上的类型参数不匹配错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75038278/

相关文章:

arrays - 为什么用reqwest下载的PNG图像的字节与使用Python下载的字节不同?

rust - 将 Ref<Box<dyn Any>> 向下转换为 Ref<Box<T>> 时处理向下转换错误

rust - 如何将引用返回到 Rc<RefCell<>> 函数参数?

rust - 我如何告诉 Cargo 构建 main.rs 以外的文件?

rust - 将具有牛场的结构转换为拥有的便捷方法

arrays - 如何动态设置 Rust 数组长度?

rust - 在Vulkan计算管道中使用输入和输出缓冲区

string - Rust 中不区分大小写的字符串匹配

rust - 如何实现 ToString 特征以创建没有尾随逗号的逗号分隔字符串?

rust - 通过 channel 发送 Vec<Box<Trait>>