2017-06-09 7 views
6

Chcę napisać funkcję, która pobiera tablicę z każdego rodzaju, w tym i zwraca ostatni element tablicy, więc próbowałem:Jak przekonwertować `& T` na po prostu` T`?

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

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

i że wydaje się działać, ale kiedy stosować mała korekta:

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

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

Wtedy ja spotkałem się z:

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

Jak przekonwertować &T do zaledwie T?

+2

wszelki wypadek, nie [metoda 'last'] (https://doc.rust-lang.org/stable/std/primitive.slice.html#method.last) dla wycinka – red75prime

Odpowiedz

8

W pierwszym przykładzie, wracasz do &T i biorąc odniesienie do czegoś, więc wartość i typy dopasowania:

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

Ale potem powiedział, że nie zamierza zwrócić odwołanie już, , ale nie zmieniła implementacji.

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

T, &T i &mut T są wszystkie rodzaje od siebie! Oznacza to, że jest taka sama jak tej "małej korekty":

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

odrzućmy & z organizmu:

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

Ups ...

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

to jest dobrze wyjaśnione w What does "cannot move out of indexed content" mean?.


Odpowiedź na pytanie brzmi: nie ma jednej właściwej drogi. Istnieją trzy szerokie możliwości:

  1. typ implementuje Copy i kompilator automatycznie dereferences to dla ciebie:

    fn last_copy<T: Copy>(slice: &[T]) -> T { 
        slice[slice.len()-1] 
    } 
    
  2. typ implementuje Clone, więc można jawnie wywołać Clone aby go powielać:

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

    Mogą być również inne metody na twoim typie, które wykonują coś podobnego.

  3. Ty nie. Czasami, jeśli masz referencję, nie możesz uzyskać odpowiedniej wartości. W takich przypadkach musisz ponownie ocenić swój projekt.

Powiązane problemy