如何将`&T`转换为只有`T`?

6

我想编写一个函数,该函数接收任何类型的数组作为参数,并返回该数组的最后一个元素,因此我尝试了以下代码:

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


2
以防万一,切片有一个名为 method last 的方法。 - red75prime
1个回答

9
在你的第一个例子中,你返回了一个&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是不同的类型!这意味着它与这个“小调整”是一样的:

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

让我们从body中删除&

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. The type implements Copy and the compiler automatically dereferences it for you:

    fn last_copy<T: Copy>(slice: &[T]) -> T {
        slice[slice.len()-1]
    }
    
  2. The type implements Clone, so you can explicitly call Clone to duplicate it:

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

    There might also be other methods on your type that do something similar.

  3. You don't. Sometimes, if you have a reference, you can't get a corresponding value. In those cases, you need to re-evaluate your design.


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