2016-04-08 7 views
0

Warum funktioniert der folgende Code, wenn Cloned einen DoubleEndedIterator<Item=&'a T> erwartet, aber iter() gibt Iterator<T> zurück (anstelle von Iterator<&T> wie erwartet)?Wie funktioniert der Iterator-Adapter "Cloned" mit "Iterator <T>"?

use std::clone::Clone; 
use std::iter::{Rev, Cloned}; 
use std::fmt::Debug; 

fn reversed<'a, U, T>(iter: U) -> Rev<Cloned<U>> 
    where U: DoubleEndedIterator<Item=&'a T>, 
      T: 'a + Clone + Debug 
{ 
    iter.cloned().rev() 
} 

fn main() { 
    let v0 = (0..10).collect::<Vec<u32>>(); 
    let mut v0r = v0.clone(); 
    v0r.reverse(); 

    assert_eq!(v0r, reversed(v0.iter()).collect::<Vec<_>>()); 
} 

Antwort

2

T ist generischer Parameter, und es hat einen Umfang, in dem sie gilt. Spezifisch ist der T Parameter für std::slice::Iterverschieden von T deklariert auf reversed. Wenn dies nicht der Fall wäre, wäre es meiner Meinung nach grundsätzlich unmöglich, dass Menschen Generika verwenden. Es wäre so, als würde jede Variable, die name genannt wird, dasselbe bezeichnen!

aber iter() gibt ein Iterator<T>

Das ist nicht wahr; Sie können derzeit kein Merkmal zurückgeben. Sie können nur einen Typ zurückgeben, der ein Merkmal implementiert. Zusätzlich std::slice::Iter<T> implementiert Iterator durch Rückkehr Verweise auf T:

impl<'a, T> Iterator for Iter<'a, T> { 
    type Item = &'a T 
} 
+0

„Insbesondere die T-Parameter für std :: Scheibe :: Iter unterscheidet sich von der T auf Umkehr erklärt“ Das ist wohl wahr, im allgemeinen Fall wenn es keine Verbindung zwischen den beiden gibt, hatte ich den Eindruck, dass 'Item = & 'ein T' in' DoubleEndedIterator 'diese separaten' T's verknüpft. Trotzdem vielen Dank für Ihre Antwort, der zweite Teil beantwortet meine Frage. –