2015-03-30 16 views
9

Mam cechę ze skojarzonego typu oraz struktury rodzajowej ::Dopasowane ogólny parametr przypisany typ w IMPL

trait Generator { 
    type Foo; 
    fn generate(&self) -> Self::Foo; 
} 

struct Baz<A, B> 
where 
    A: Generator, 
{ 
    generator: A, // will be some struct implementing Generator, but the exact type will vary 
    vec: Vec<B>, // Each element will be A::Foo 
} 

chcę generate i włóż ją do mego Vector:

impl<A: Generator, B> Baz<A, B> { 
    fn addFoo(&mut self) { 
     self.vec.push(self.generator.generate()); 
    } 
} 

Uh-oh! Błąd kompilacji:

error[E0308]: mismatched types 
    --> src/main.rs:16:27 
    | 
16 |    self.vec.push(self.generator.generate()); 
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found associated type 
    | 
    = note: expected type `B` 
       found type `<A as Generator>::Foo` 

Fair enough, muszę wyjaśnić, że kompilator B jest taka sama jak A::Foo; spróbujmy z where:

impl<A: Generator, B> Baz<A, B> 
where 
    A::Foo = B, 
{ 

który nie pomaga:

error: equality constraints are not yet supported in where clauses (#20041) 
    --> src/main.rs:16:5 
    | 
16 |  A::Foo = B, 
    |  ^^^^^^^^^^ 

Hmm, nie ma sobie równych. Może mogę to zrobić za pomocą operatora dwukropka?

impl<A: Generator, B> Baz<A, B> 
where 
    B: A::Foo, 
{ 
error[E0405]: cannot find trait `Foo` in `A` 
    --> src/main.rs:16:11 
    | 
16 |  B: A::Foo, 
    |   ^^^ not found in `A` 

Nie, teraz to narzekają A. Może powinienem powiedzieć Generator?

impl<A: Generator, B> Baz<A, B> 
where 
    B: Generator::Foo, 
{ 
error[E0404]: expected trait, found associated type `Generator::Foo` 
    --> src/main.rs:16:8 
    | 
16 |  B: Generator::Foo, 
    |  ^^^^^^^^^^^^^^ not a trait 

No dobra praca, kompilator - to nie cecha; jest to typ powiązany, ale to nie mówi mi, jak napisać klauzulę where, która pasuje do niego.

+0

Czy na pewno chcesz podtypu Generator? – llogiq

Odpowiedz

15

I must explain to the compiler that B is the same as A::Foo

Istnieje specjalna składnia do niego:

impl<A, B> Baz<A, B> 
where 
    A: Generator<Foo = B>, 
{ 
    fn add_foo(&mut self) { 
     self.vec.push(self.generator.generate()); 
    } 
} 
+0

Myślę, że jest to odpowiedź na to, o co prosi, a nie to, czego chce. Dzięki, nie wiedziałem o tej składni. –

4

Można pozbyć się rodzajowy argumentu B i zamiast ograniczać B bezpośrednio przejść A::Foo jako drugi argument do Baz generycznych, ale nie jestem pewien, czy rzeczywisty problem dopasowuje uproszczony przykład pan pokazał.

impl<A: Generator> Baz<A, A::Foo> { 
    fn addFoo(&mut self) { 
     self.vec.push(self.generator.generate()); 
    } 
} 
8

Sztuką jest tylko jeden ogólny parametr:

trait Generator { 
    type Foo; 
    fn generate(&self) -> Self::Foo; 
} 

struct Baz<G> 
where 
    G: Generator, 
{ 
    generator: G, 
    vec: Vec<G::Foo>, 
} 

impl<G> Baz<G> 
where 
    G: Generator, 
{ 
    fn add_foo(&mut self) { 
     self.vec.push(self.generator.generate()); 
    } 
} 

Ponieważ wektor będzie zawierać G::Foo, możemy tylko powiedzieć, że rzeczywiście.

Styl rdzy to snake_case, więc zaktualizowałem go tak, aby utworzyć parametr typu G, aby pomóc czytelnikowi.

Powiązane problemy