2015-08-05 11 views
7

Ho due mie classi A e B e voglio usare una HashMap. Ho un codice come questo:Come implementare Eq e Hash per le mie proprie strutture per usarli in HashMap?

use std::collections::HashMap; 

pub struct A 
{ 
    x: i32, 
    y: i32, 
    title: String, 
    b_obj: B, 
} 

pub struct B 
{ 
    a: u32, 
    b: u32, 
    a_obj: A, 
} 

fn main() 
{ 
    let map = HashMap::new(); 
    map.insert(A{x: 10, y: 20, title: "test".to_string()}, B{a: 1, b: 2}); 
} 

Ma il compilatore mi da questi errori:

error: the trait core::cmp::Eq is not implemented for the type A [E0277]
error: the trait core::hash::Hash is not implemented for the type A [E0277]

So che devo implementare queste caratteristiche, ma dopo ore di ricerca internet ho trovato nulla di attuazione loro.
Per favore, dammi un esempio su come farlo.

Modifica: In realtà, il mio codice è più complicato e le mie strutture contengono altre strutture (ho modificato il codice). E il compilatore si lamenta che non ho implementato l'Eq.

Il tratto di hash che ho implementato. Sembra così adesso. La mia applicazione è come questo:

impl Hash for Application { 
    fn hash<H>(&self, state: &mut H) where H: Hasher { 
    state.write_u32(self.pid); 
     state.finish(); 
    } 
} 

ho fatto un impl per PartialEq anche:

impl PartialEq for Application { 
    fn eq(&self, other: &Application) -> bool { 
    self.pid == other.pid 
    } 
} 

Ma il compilatore si lamenta Eq:

error: the trait core::cmp::Eq is not implemented for the type app::Application

Come posso implementare Eq? ?? Perché non c'è implementazione nei documenti?

+0

Le tue strutture sono reciprocamente ricorsive, ognuna contiene un campo dell'altro tipo in base al valore. Questo non può essere compilato così com'è. – barjak

+1

Penso che il tuo impl di 'Hash' dovrebbe semplicemente essere 'self.pid.hash (stato)'. Per me è un errore chiamare "finish". – barjak

risposta

3

Eq è ciò che chiamiamo un tratto di marcatore: non ha un metodo a sé stante, è solo un modo per il programmatore di esprimere che la sua struttura verifica una certa proprietà. È possibile implementare in questo modo:

impl Eq for Application {} 

Oppure, in alternativa, utilizzare #[derive(Eq)] in cima alla dichiarazione di applicazione.

Eq è un tratto vincolato da PartialEq. Ciò significa che è possibile implementarlo solo su strutture che implementano anche PartialEq (che è il caso qui). Implementando Eq, si promette che l'implementazione di PartialEq è riflessa (vedere i documenti per cosa significa).

+0

grazie. Penso che questo debba essere nei documenti da qualche parte. – Revertron

+0

Infatti, ci dovrebbero essere alcuni esempi nel doc dell'API per 'Eq' e' ParialEq'. Proverò ad aggiungerne presto. – barjak

4

Si può avere il compilatore derivano queste istanze per voi inserendo la seguente prima della dichiarazione struct:

#[derive(PartialEq, Eq, Hash)] 
pub struct A 
    ... 

Si potrebbe naturalmente li implementano manualmente. Se vuoi farlo, dovresti leggere la documentazione su traits, Eq e Hash.

+2

la domanda è come scrivere la propria implementazione di hash? – Revertron

+2

raramente c'è ragione per farlo ... Ma come ha scritto @fjh, se sai quale caratteristica implementare, consulta la documentazione. In caso di problemi, inserisci il codice che hai provato. –