Come posso implementare un tratto che non possiedo per un tipo che non possiedo?

Volevo implementare il tratto Shl per Vec , il codice è sotto. Ciò renderebbe ansible cose come vec << 4 , che sarebbe un buon zucchero per vec.push(4) .

 use std::ops::Shl; impl Shl for Vec { type Output = Vec; fn shl(&self, elem: &T) -> Vec { self.push(*elem); *self } } fn main() { let v = vec![1, 2, 3]; v << 4; } 

La compilazione non riesce con il seguente errore:

non può fornire un’implementazione dell’estensione in cui sia tratto che tipo non sono definiti in questa cassa [E0117]

o

il parametro type T deve essere utilizzato come parametro type per un tipo locale (ad esempio, MyStruct ); solo i tratti definiti nella cassa corrente possono essere implementati per un parametro di tipo [E0210]

A quanto ho capito, dovrei applicare patch allo stdlib, in particolare alla collections::vec crate. C’è un altro modo per cambiare questo codice per compilare correttamente?

    Anche se non è ansible farlo esattamente, la solita soluzione è quella di avvolgere semplicemente il tipo che si desidera nel proprio tipo e implementare il tratto su quello.

     use somecrate::FooType; use somecrate::BarTrait; struct MyType(FooType); impl BarTrait for MyType { fn bar(&self) { // use `self.0` here } } 

    Ciò renderebbe ansible cose come vec < < 4 , che sarebbe un buon zucchero per vec.push(4) .

    Anche se può essere fatto, è generalmente una ctriggers idea implementare un operatore con una semantica inaspettata.

    Ecco un esempio di come questo può essere fatto:

     use std::ops::Shl; struct BadVec(Vec); impl Shl for BadVec { type Output = BadVec; fn shl(mut self, elem: T) -> Self::Output { self.0.push(elem); self } } fn main() { let mut v = BadVec(vec![1, 2, 3]); v = v < < 4; assert_eq!(vec![1, 2, 3, 4], v.0) } 

    Se implementi Deref ( DerefMut ):

     use std::ops::{Deref, DerefMut}; impl Deref for BadVec { type Target = Vec; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for BadVec { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } 

    puoi chiamare i metodi Vec :

     fn main() { let mut v = BadVec(vec![1, 2, 3]); v = v < < 4; v.truncate(2); assert_eq!(2, v.len()); } 

    Dai un'occhiata alla cassa newtype_derive , è in grado di generare per te un codice newtype_derive .