2015-05-15 18 views
5

Cercando di implementare il tratto Debug per un tipo personalizzato, mi sono imbattuto nell'implementazione di Vec<T>. Ho difficoltà a capire come funziona.Informazioni sull'implementazione di debug per Vec <T>

L'implementazione è questa:

impl<T: fmt::Debug> fmt::Debug for Vec<T> { 
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 
     fmt::Debug::fmt(&**self, f) 
    } 
} 

ho capito che definisce l'implementazione fmt per qualche altro tipo. Quello che non riesco a capire è di che tipo si tratta. Ho provato a capirlo con l'aiuto di another question e cercando tra implementations of Debug per qualcosa che sembra appropriato (forse qualcosa come &[T]), ma senza successo.

Qual è il significato esatto di &**self in questo contesto? Quale implementazione di Debug viene chiamata?

risposta

8

In casi come questo, trovo utile fare in modo che il compilatore ti dica di che tipo si tratta. Provoca solo un errore di tipo e lascia che sia il diagnostico del compilatore a farlo per te. Il modo più semplice è quello di cercare di assegnare il vostro articolo a qualcosa di tipo ():

fn main() { 
    let v = &vec![1,2,3]; 
    let() = v; 
    let() = &**v; 
} 

Gli errori sono:

<anon>:3:9: 3:11 error: mismatched types: 
expected `&collections::vec::Vec<_>`, 
    found `()` 
(expected &-ptr, 
    found()) [E0308] 
<anon>:3  let() = v; 
       ^~ 
<anon>:4:9: 4:11 error: mismatched types: 
expected `&[_]`, 
    found `()` 
(expected &-ptr, 
    found()) [E0308] 
<anon>:4  let() = &**v; 
       ^~ 

Così v è un &collections::vec::Vec<_> e &**v è un &[_].

più dettagliate, Vec ha questo:

impl<T> Deref for Vec<T> { 
    type Target = [T]; 
    // ... 
} 

Così, abbiamo dereference una volta per andare da &Vec<T> ad un Vec<T>, dereferenziazione nuovo per ottenere un [T], e quindi fare riferimento una volta per ottenere un &[T].

[T] ha questo:

impl<T> Debug for [T] { 
    fn fmt(&self, ...) ...; 
} 

Tuttavia, durante la ricerca di un metodo appropriato per chiamare, Rust sarà automatically attempt to dereference il bersaglio. Ciò significa che possiamo trovare il metodo su [T] da un &[T].

Come corrected by Francis Gagné, Debug::fmt prende &self, quindi chiamando direttamente con un &[T] trova l'attuazione corrispondente. Non è necessario alcun riferimento o dereferenziamento automatico.

+0

Grazie! Mi manca solo una cosa: ho trovato un'implementazione per '[T]' ma non per '& [T]', è quest'ultima a essere chiamata? Perché? – toro2k

+1

@ toro2k Ho aggiunto un po 'di più a riguardo. Fatemi sapere se aiuta! – Shepmaster

+2

Non penso ci sia alcun auto-dereferenziamento (o auto-referenziamento), perché 'fmt :: Debug :: fmt()' prende 'self' per riferimento, cioè si aspetta un' & [T] ', ed è dato un '& [T]'. –

Problemi correlati