2015-05-25 17 views
6

Mam problem projektowania, przy użyciu mniej więcej tak:Jak wdrożyć cechę dla sparametryzowane cechy

trait MyTrait<K: OtherTrait> { ... } 

impl<K: OtherTrait, M: MyTrait<K>> AnyTrait for M { ... } 

nie mogę realizować cechy dla tej cechy z powodu błędu E207 ("parametru type K nie jest ograniczony przez cechę impaktu, typ siebie lub predykaty ").

Znalezienie żadnego sposobu, aby pozbyć się tego błędu, mogę ubiegać this not-so-good-looking workaround (gadatliwy i struct bez wartości wewnętrznej):

use std::fmt; 
use std::marker::PhantomData; 

pub trait MyTrait<K: fmt::Display> { 
    fn get_some_k(&self) -> Option<K>; 
} 

/* // This is my target impl but results in E207 due to K not constrained 
impl<K: fmt::Display, S: MyTrait<K>> fmt::Display for S { 
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 
     write!(f, "{}", self.get_some_k().unwrap()) 
    } 
} */ 
pub struct Ugly<'a, K: fmt::Display, S: 'a + MyTrait<K>>(&'a S, PhantomData<K>); 
impl<'a, K: fmt::Display, S: MyTrait<K>> fmt::Display for Ugly<'a, K, S> { 
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 
     write!(f, "{}", self.0.get_some_k().unwrap()) 
    } 
} 

fn main() { } 

myślę, że powinien być jakiś ładniejszy sposób zaimplementować cechy dla tego rodzaju sparametryzowana cecha.

Nie znalazłem dobrego przykładu w standardzie (na przykład brak implementacji Display w cechach z powiązanym typem, takim jak Iterator)?

+0

Pomyślałem, że wspomnę o tym, że mam dokładnie ten sam problem, ale nie mam luksusu owijać kocem w "Ugly", ponieważ "MyTrait" jest publiczną cechą narażoną na działanie użytkowników, i wymagające od nich użycia "Ugly" gruntownie niszczy API, dodając niepotrzebną złożoność. – mindTree

+0

Możliwy duplikat [Zapewniając implementacje cech dla niestandardowej cechy] (http://stackoverflow.com/questions/32430659/providing-blanket-trait-implementations-for-a-ustom-trait) – wimh

Odpowiedz

2

Here’s an implementation using associated types (co oznacza, że ​​można tylko wdrożyć MyTrait jednego K za typ):

use std::fmt; 

pub trait MyTrait { 
    type K: fmt::Display; 
    fn get_some_k(&self) -> Option<Self::K>; 
} 

impl<S: MyTrait> fmt::Display for S { 
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 
     write!(f, "{}", self.get_some_k().unwrap()) 
    } 
} 

fn main() { } 

Jednak, gdy wyjaśnione jak to staje się jasne, że podejście to nie będzie działało, bo jesteś implementacja Display dla wszystkich typów implementujących MyTrait -typów, które mogą mieć własną implementację Display. To jest zabronione, a więc masz E0210:

error: type parameter S must be used as the type parameter for some local type (e.g. MyStruct<T>); only traits defined in the current crate can be implemented for a type parameter [E0210]

owijając go w coś podobnego do Twojego Ugly nie-jest to jedyny sposób, aby umożliwić taką realizację. Możesz też zaimplementować cechę we własnej skrzyni, a nie jedną w cudzej (np. Display).

+0

dzięki, pomyślałem o skojarzonym typ, ale jestem w przypadku, gdy potrzebuję wielu implementacji dla każdego typu, inaczej wykonałbym to zadanie (moim przypadkiem użycia nie jest 'Display'). – cheme

Powiązane problemy