如何将实现特定trait的对象数组传递给函数?

6
为了学习Rust语法,我决定实现一个函数来对传入的数组进行排序:
fn sort(array) {
    // actual sorting
}

这个问题中,我找到了如何传递数组并更改其内容,但是除此之外,数组必须由可以相互比较的类型组成。我找到了std::cmp::PartialOrd trait,并发现数组的元素需要实现它。
通过将这些知识与Rust书中有关动态分派的段落联系起来,我构建了像这样的东西:
use std::cmp;

fn sort(arr: &mut [&std::cmp::PartialOrd]) {
    // actual sorting
}

这段代码无法编译:

error[E0393]: the type parameter `Rhs` must be explicitly specified
 --> src/lib.rs:3:21
  |
3 | fn sort(arr: &mut [&std::cmp::PartialOrd]) {
  |                     ^^^^^^^^^^^^^^^^^^^^ missing reference to `Rhs`
  |
  = note: because of the default `Self` reference, type parameters must be specified on object types

有没有正确的语法来实现将实现某个 trait 的对象数组传递给函数?
2个回答

7
语法并不是问题。我将尝试解释一下,为什么你想要做的事情有点靠不住,所以你可能无法使用特质对象使其正常工作:
你的sort函数的参数类型是&mut [&PartialOrd]。一般来说,&mut [&Trait]表示“一个可变值的切片,可以是任何类型,只要它们实现了Trait”。然而,请注意,切片中的值可能具有不同的类型。由此产生的问题是:如果切片包含不同类型的值,例如Float和String,那么在sort中应该发生什么?仅仅因为浮点数和字符串都可以进行比较,并不意味着你可以有意义地将浮点数与字符串进行比较。这基本上就是错误信息指出的问题。
你正在使用的语法是正确的。例如,以下代码(可能按元素的字符串表示对数组进行排序)可以编译:
fn sort(arr: &mut [&ToString]) {
    // sort by string representation
}

但是你实际上想要做的可能只是使用一个通用函数,如下所示(因为动态分派在这里并没有太多意义):

fn sort<T: PartialOrd>(arr: &mut [T]) {
    // do the sorting
}

这段代码与您原来的代码类似,但它为任何实现了PartialOrd的类型T定义了sort。与您的代码的重要区别在于,切片中的所有元素都必须是相同类型的,因此不会出现处理不同类型值的问题。


1
也许值得注意的是:&mut [&Trait] 是一个对实现了 Trait 类型的元素的引用切片。这些元素存储在其他地方,而不是在数组中连续存储(这是不可能的,因为数组是同质的)。对引用数组进行排序很少是用户想要的。 - Lukas Kalbertodt

3
问题在于函数定义。
fn sort(arr: &mut [&std::cmp::PartialOrd]) {
    // actual sorting
}

如果您修改函数并包含类型参数,那么程序就可以编译:

fn sort<T>(arr: &mut [T])
where
    T: PartialOrd,
{
}

fn main() {}

请注意,你不是传递一个 数组,而是一个 切片。在 Rust 中,数组是由它所包含的类型以及它的长度定义的。

a: [i32; 10] // defines an array that stores `i32` and has length 10
a: [i32] // defines a slice of i32

同时注意,在编译程序时,默认情况下已包含PartialOrd trait,所以无需使用完全限定名称。您可以使用PartialOrd而不是std :: cmp :: PartialOrd。请参阅std :: prelude


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接