Rust中的以下代码可以正常编译:

pub fn insertion_sort(data : &mut [int]){
  let n  = data.len();
  for j in range(1, n){
    let key = data[j];
    // we insert data[j] into the sorted sequence
    //data[0...j-1]
    let mut i = j -1;
    while data[i] > key{
        data[i + 1]  = data[i];
        if i == 0{
            break;
        }
        i -= 1;
    }
    data[i] = key;
  }
}

但此刻,我将介绍泛型,如下所示:
pub fn insertion_sort<T : Ord>(data : &mut [T]){
  let n  = data.len();
  for j in range(1, n){
    let key = data[j];
    // we insert data[j] into the sorted sequence
    //data[0...j-1]
    let mut i = j -1;
    while data[i] > key{
        data[i + 1]  = data[i];
        if i == 0{
            break;
        }
        i -= 1;
    }
    data[i] = key;
  }
}

编译器报告以下问题:



从用于内置类型的非通用代码转换为通用代码时,我们需要特别注意吗?错误消息听起来很神秘。

[编辑]

根据以下弗拉基米尔(Vladimir)的建议,我尝试使用切片的交换功能想出一个适用于T:Ord的版本
pub fn insertion_sort<T : Ord>(data : &mut [T]){
  let n  = data.len();
  for j in range(1, n){
    // we insert data[j] into the sorted sequence
    //data[0...j-1]
    let mut i = j -1;
    while data[i] > data[i+1]{
        data.swap(i + 1, i);
        if i == 0{
            break;
        }
        i -= 1;
    }
  }
}

最佳答案

是的,您需要格外小心,因为在原始代码段中,您使用了int,它可以隐式地复制(实现 Copy 特性),而在第二段代码中,您仅使用了带有Ord绑定(bind)的通用参数。默认情况下,Rust中的值是移动的,而不是复制的,这确实对您可以使用的值带来了一些限制。如果您编写的是<T: Ord+Copy>而不是<T: Ord>,则可以观察到这一点-您的代码将重新开始编译。但是,这不是适当的通用解决方案,因为很多类型不是Copy

首先,您应该阅读the official Rust guide,它解释了所有权和借用权以及除其他以外的Rust核心概念,这些概念对于有效使用Rust必不可少。您看到的错误是这些概念的结果。基本上,如果您对某个数据结构具有引用,则不能将任何内容移出该结构。切片是对连续数据块的引用;因为您没有指定Copy上绑定(bind)的T,所以Rust无法从切片中复制值,并且它也无法移动这些值,因为禁止从引用后面移动。因此它发出一个错误。

这样的行为听起来是限制性的,有时是限制性的。用其他语言(大多数是C语言)非常自然地完成的许多事情不能直接在Rust中完成。作为返回,Rust提供了巨大的安全保证。但是,有时候您确实需要编写本身是安全的东西,但是这种安全性对于编译器而言并不明显。当您实现基本的数据结构和算法(例如排序)时,通常会发生这种情况。最终的工具当然是unsafe块,但是在这种情况下,您将不需要它们。 Rust在 std::mem 模块中提供了几个非常有用的功能,尤其是 swap() replace() 。但是,专门针对切片,直接在切片上有一种称为 swap() 的方法。它在给定索引处交换元素。如果以交换操作的形式重新定义插入排序,则将能够编写完全通用的代码,即使这些代码不可复制,它们也适用于所有Ord类型。我强烈建议您尝试此操作,因为这将帮助您了解如何编写底层的Rust程序。

另一方面,如果您事先知道只能使用基本类型(例如int),则可以安全地将Copy绑定(bind)到T上,并保持原样。或者,您可以使用更多通用的Clone绑定(bind),但是从切片中提取值时,您将需要调用clone()方法:

pub fn insertion_sort<T: Ord+Clone>(data: &mut [T]) {
  let n = data.len();
  for j in range(1, n) {
    let key = data[j].clone();
    // we insert data[j] into the sorted sequence
    //data[0...j-1]
    let mut i = j -1;
    while data[i] > key {
        data[i + 1] = data[i].clone();
        if i == 0 {
            break;
        }
        i -= 1;
    }
    data[i] = key;
  }
}

关于generics - 在对模板进行模板化时,使用rust 报告不能脱离取消引用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26460738/

10-15 16:36