2016-04-21 21 views
6

oto scenariusz: Mam strukturę i cechę parę następująco:Ograniczenia rdzy do Generic Type Reference

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. 
    } 
} 

Operacja wymaga połączenia przekazywany przez wartość, kiedy używany, a problem przychodzi z czymś podobnym do "zrobić coś". Wolałbym nie wymuszać semantyki kopii dla typu T i chciałbym obejść ten problem. Zasadniczo chciałbym wiedzieć, co następuje:

  1. Czy można wymusić ograniczenia cech na referencjach parametrów typu? Coś w stylu: struct Container<T: Sized + Operation> where &T: Operation { ... }. Próbowałem trochę poskładać składnię i nie osiągnąłem żadnego sukcesu.
  2. Jeśli powyższe nie jest obecnie możliwe, czy jest to teoretycznie możliwe; to znaczy nie narusza żadnych właściwości koherencji lub czegoś podobnego?
  3. byłoby możliwe, aby utworzyć drugą cechę, powiedzmy Middle: Operation, gdzie Middle mogą wymagać, aby jakikolwiek realizatorów Middle, T, aby również być wymagane do wdrożenia Operation dla &T.
  4. Jeśli żadna z powyższych metod nie jest możliwa, czy istnieje inne typowe obejście tego problemu?

Niektóre Uwagi:

  • nie mam dostępu, aby zmienić cechę Operation, to biorąc pod uwagę i to, co mam pracować.
  • Istnieje old RFC, który mówi o pewnych modyfikacjach klauzul where, ale nie znalazłem nic związanego z ograniczeniami referencyjnymi. Wersja
  • kompilator: rustc 1.8.0 (db2939409 2016-04-11)

Odpowiedz

9

Tak, można ograniczyć &T być Sized + Operation. Musisz użyć Higher-Rank Trait Bounds i 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()); 
} 

drukuje

1 
+1

To jest wielki. Czytałem książkę wiele razy, a HRTB było dla mnie źródłem nieporozumień. Ta odpowiedź pomogła mi (i nie jestem OP!). Dzięki jeszcze raz! –

+0

Nie ma ich obecnie w książce :(będą w drugiej edycji –

+0

Ograniczenia mogą mieć HRTB. T: "static" (nie zawiera pożyczonych danych). – bluss