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

Ube*_*per 6 generics rust

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

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

fn last<T: Clone>(slice: &[T]) -> &T {
    &slice[slice.len()-1]
}
Run Code Online (Sandbox Code Playgroud)

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

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

fn last<T: Clone>(slice: &[T]) -> T {
    &slice[slice.len()-1]
}
Run Code Online (Sandbox Code Playgroud)

然后我遇到了:

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

如何将其转换&T为刚好T

She*_*ter 8

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

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

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

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

T,&T并且&mut T彼此都是不同的类型!这意味着它与"小调整"相同:

fn foo() -> i32  { 42 } // Before
fn foo() -> bool { 42 } // After
Run Code Online (Sandbox Code Playgroud)

让我们放弃&身体:

fn last<T: Clone>(slice: &[T]) -> T {
    slice[slice.len()-1]
}
Run Code Online (Sandbox Code Playgroud)

糟糕!

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

这是很好的解释什么是"不能搬出索引内容的"呢?.


你的问题的答案是:没有一个正确的方法.有三种可能性:

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

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

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

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

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