如何将`& T`转换为'T`?

时间:2017-06-09 23:29:37

标签: generics rust

我想写一个函数,它接受一个包含任何类型的数组,并返回数组的最后一个元素,所以我试过了:

fn main() {
    let v = ["a", "b"];
    println!("{}", last(&v));
}

fn last<T: Clone>(slice: &[T]) -> &T {
    &slice[slice.len()-1]
}

这似乎有效,但是当我应用一个小调整时:

fn main() {
    let v = ["a", "b"];
    println!("{}", last(&v));
}

fn last<T: Clone>(slice: &[T]) -> T {
    &slice[slice.len()-1]
}

然后我遇到了:

error[E0308]: mismatched types
 --> <anon>:9:5
  |
9 |     &slice[n-1]
  |     ^^^^^^^^^^^ expected type parameter, found &T
  |
 = note: expected type `T`
            found type `&T`

如何将&T转换为T

1 个答案:

答案 0 :(得分:8)

在您的第一个示例中,您将返回&T并引用某个内容,因此值和类型匹配:

fn last<T: Clone>(slice: &[T]) -> &T {
//                                ^^
    &slice[slice.len()-1]
//  ^
}

但是,那时你说你再也不会返回一个引用,但是没有改变实现

fn last<T: Clone>(slice: &[T]) -> T {
//                                ^
    &slice[slice.len()-1]
//  ^
}

T&T&mut T都是彼此不同的类型!这意味着它与此相同&#34;小调整&#34;:

fn foo() -> i32  { 42 } // Before
fn foo() -> bool { 42 } // After

&从身体中删除:

fn last<T: Clone>(slice: &[T]) -> T {
    slice[slice.len()-1]
}

糟糕...

error[E0507]: cannot move out of indexed content
 --> src/main.rs:4:9
  |
4 |         slice[slice.len()-1]
  |         ^^^^^^^^^^^^^^^^^^^^ cannot move out of indexed content

What does "cannot move out of indexed content" mean?中详细说明了这一点。

你的问题的答案是:没有人正确的方法。有三种可能性:

  1. 类型实现Copy,编译器会自动为您解除引用:

    fn last_copy<T: Copy>(slice: &[T]) -> T {
        slice[slice.len()-1]
    }
    
  2. 该类型实现Clone,因此您可以显式调用Clone来复制它:

    fn last_clone<T: Clone>(slice: &[T]) -> T {
        slice[slice.len()-1].clone()
    }
    

    您的类型可能还有其他方法可以执行类似的操作。

  3. 。有时,如果您有参考,则无法获得相应的值。在这些情况下,您需要重新评估您的设计。