2016-04-21 19 views
6

Ecco lo scenario: ho una struttura e un paio tratto come segue:Vincoli Rust per tipo generico riferimento

trait Operation { 
    fn operation(self) -> u32 
} 

struct Container<T: Sized + Operation> { 
    x:T 
} 

impl <T: Sized + Operation> for Container<T> { 
    fn do_thing(&self) -> u32 { 
     // Do something with the field x. 
    } 
} 

L'operazione richiede una chiamata passaggio per valore ogni volta utilizzato, e la questione viene fornito con qualcosa di simile a "fare". Preferirei non dover forzare la semantica della copia per il tipo T e vorrei una soluzione alternativa per questo. In sostanza vorrei sapere quanto segue:

  1. È possibile imporre vincoli trait sui riferimenti dei parametri di tipo? Qualcosa sulla falsariga di: struct Container<T: Sized + Operation> where &T: Operation { ... }. Ho provato un po 'con la sintassi, e non ho avuto alcun successo.
  2. Se quanto sopra non è attualmente possibile, è teoricamente possibile; cioè non violare alcuna richiesta di coerenza delle proprietà o qualcosa del genere?
  3. Sarebbe possibile creare un secondo tratto, dire Middle: Operation, dove Middle può richiedere che esso implementatori di Middle, T, per essere tenuti ad attuare Operation per &T.
  4. Se nessuno dei precedenti è possibile, esiste qualche altra soluzione comune per questo?

Alcune note:

  • io non ho accesso a cambiare il Operation tratto, è dato ed è quello che sto per lavorare.
  • C'è un old RFC che parla di alcune modifiche alle clausole where, ma non ho trovato nulla relativo ai vincoli di riferimento. Versione
  • compilatore: rustc 1.8.0 (db2939409 2016-04-11)

risposta

9

Sì, è possibile limitare &T essere Sized + Operation. È necessario utilizzare Higher-Rank Trait Bounds e where.

trait Operation { 
    fn operation(self) -> u32; 
} 

struct Container<T> 
    where for<'a> &'a T: Sized + Operation 
{ 
    x: T, 
} 

impl<T> Container<T> 
    where for<'a> &'a T: Sized + Operation 
{ 
    fn do_thing(&self) -> u32 { 
     self.x.operation() 
    } 
} 

impl<'a> Operation for &'a u32 { 
    fn operation(self) -> u32 { 
     *self 
    } 
} 

fn main() { 
    let container = Container { x: 1 }; 
    println!("{}", container.do_thing()); 
} 

stampe

1 
+1

Questo è grande. Ho letto il libro più volte e HRTB sono stato fonte di confusione per me. Questa risposta mi ha aiutato (e io non sono l'OP!). Grazie ancora! –

+0

Non sono attualmente nel libro :(saranno nella seconda edizione –

+0

HRTB può essere limitante.Il limite 'per <'a> & 'a T: Operation' richiede implicitamente' per <'a> T:' a', in pratica quello ' T: 'statico' (non contiene dati presi in prestito). – bluss

Problemi correlati