2017-06-09 13 views
6

Tôi muốn viết một hàm mang theo trong một mảng với bất kỳ loại trong đó và trả về phần tử cuối cùng của mảng, vì vậy tôi đã cố gắng:Làm cách nào để chuyển đổi `& T` thành` T`?

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

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

và điều đó dường như làm việc, nhưng khi tôi áp dụng một sự điều chỉnh nhỏ:

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

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

Sau đó, tôi đang gặp:

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

làm thế nào để chuyển đổi các &T chỉ T?

+2

Chỉ trong trường hợp, có [phương thức 'cuối cùng] (https://doc.rust-lang.org/stable/std/primitive.slice.html#method.last) cho lát cắt – red75prime

Trả lời

8

Trong ví dụ đầu tiên của bạn, bạn đang trở về một &T và tham gia một tham chiếu đến một cái gì đó, vì vậy giá trị và các loại phù hợp:

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

Nhưng, sau đó bạn nói bạn đã không sẽ trả về một tài liệu tham khảo nữa, nhưng không thay đổi triển khai.

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

T, &T&mut T là tất cả các loại khác nhau từ mỗi khác! Điều này có nghĩa nó giống như thế này "điều chỉnh nhỏ":

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

Hãy thả & khỏi cơ thể:

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

Rất tiếc ...

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

này được giải thích trong What does "cannot move out of indexed content" mean?.


Câu trả lời cho câu hỏi của bạn là: không có cách nào đúng. Có ba khả năng mở rộng:

  1. Các loại thực Copy và trình biên dịch tự động dereferences nó cho bạn:

    fn last_copy<T: Copy>(slice: &[T]) -> T { 
        slice[slice.len()-1] 
    } 
    
  2. Các loại thực Clone, vì vậy bạn có thể gọi một cách rõ ràng Clone để nhân đôi nó:

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

    Cũng có thể có các phương pháp khác trên loại của bạn có chức năng tương tự.

  3. Bạn không. Đôi khi, nếu bạn có một tham chiếu, bạn không thể có được một giá trị tương ứng. Trong những trường hợp đó, bạn cần phải đánh giá lại thiết kế của mình.

Các vấn đề liên quan