How do I implement a trait I don't own for a type I don't own?

后端 未结 2 931
忘掉有多难
忘掉有多难 2020-11-22 00:55

I wanted to implement the Shl trait for Vec, the code is below. This would make things like vec << 4 possible, which would be ni

相关标签:
2条回答
  • 2020-11-22 01:35

    This would make things like vec << 4 possible, which would be nice sugar for vec.push(4).

    Although it can be done, it is generally a bad idea to implement an operator with a unexpected semantic.

    Here is an example of how this can be done:

    use std::ops::Shl;
    
    struct BadVec<T>(Vec<T>);
    
    impl<T> Shl<T> for BadVec<T> {
        type Output = BadVec<T>;
    
        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)
    }
    

    If you implement Deref (DerefMut):

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

    you can call Vec methods:

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

    Take a look at the newtype_derive crate, it can generate some boilerplate code for you.

    0 讨论(0)
  • 2020-11-22 01:43

    While you can't do that exactly, the usual workaround is to just wrap the type you want in your own type and implement the trait on that.

    use somecrate::FooType;
    use somecrate::BarTrait;
    
    struct MyType(FooType);
    
    impl BarTrait for MyType {
        fn bar(&self) {
            // use `self.0` here
        }
    }
    
    0 讨论(0)
提交回复
热议问题