代码之家  ›  专栏  ›  技术社区  ›  Some Name

自动导出Arc的特征实现

  •  0
  • Some Name  · 技术社区  · 5 年前

    我有一个特点和 struct 实施它。这个 结构 裹着 Arc 可以调用trait的方法,但是 它本身并没有实现:

    use std::sync::Arc;
    
    trait Foo{
        fn bar(&self);
    }
    
    struct A;
    
    impl Foo for A{ 
        fn bar(&self){ }
    }
    
    fn test<A: Foo>(arc_a: Arc<A>){
        let foo_obj: & dyn Foo = &arc_a; //the trait bound `std::sync::Arc<A>: Foo` is not satisfied
    }
    

    以下代码可以正常工作:

    use std::sync::Arc;
    
    trait Foo{
        fn bar(&self);
    }
    
    struct A;
    
    impl Foo for A{ 
        fn bar(&self){ }
    }
    
    impl<A> Foo for Arc<A> //Manually implemented
    where
        A: Foo
    { 
        fn bar(&self){ self.bar() }
    }
    
    fn test<A: Foo>(arc_a: Arc<A>){
        let foo_obj: & dyn Foo = &arc_a;
    }
    

    有没有一种方法可以自动导出这种特性的实现?

    0 回复  |  直到 5 年前
        1
  •  2
  •   user2722968    5 年前

    你必须手动实现它们。而您的手动执行 Foo for Arc<A> 似乎完全微不足道,重要的部分是“隐藏”在 self.bar() ,从中自动删除 self: &Arc<A> &A .记住你的实现 为Arc设计的Foo<A> 事实上可能是完全不同的东西;但在现实世界中,我们通常只是想要“deref impl”。

    在你的第一个例子中

    fn test<A: Foo>(arc_a: Arc<A>){
        let foo_obj: &dyn Foo = &arc_a;
    }
    

    如果你这样做了,这将被编译 = &*arc_a ,作为 *arc_a 解除 Arc<A> A &*arc_a 然后是一个 &dyn Foo .

    在第二个示例中,您提供了一个手动实现 for Arc<A>

    impl<A> Foo for Arc<A> where A: Foo { 
        fn bar(&self){ self.bar() }
    }
    

    在这里,deref(在上面是显式的)现在是隐式的 自己bar() 。这样可以避免手动解除锁定,但impl可能会完全不同。例如:

    impl Foo for A{ 
        fn bar(&self){ println!("This is fine") }
    }
    
    impl<A> Foo for Arc<A>
    where
        A: Foo
    { 
        fn bar(&self) { panic!() }
    }
    
    fn test<A: Foo>(arc_a: Arc<A>){
        let foo_obj: & dyn Foo = &arc_a;
        foo_obj.bar()
    }
    
    fn main() {
        test(Arc::new(A))
    }
    

    上述程序将出现恐慌,因为 foo_obj 使用 impl for Arc<A> .如果你改变路线 test =&*阿尔卡 这个 impl for A 使用,程序将打印“这很好”。

    如果你只需要一点点 Foo 对于常见的智能指针,可以通过宏执行:

    macro_rules! deref_impl {
        ($($sig:tt)+) => {
            impl $($sig)+ {
                fn bar(&self) {
                    (**self).bar()
                }
            }
        };
    }
    deref_impl!(<'a, N> Foo for &'a N where N: Foo + ?Sized);
    deref_impl!(<'a, N> Foo for &'a mut N where N: Foo + ?Sized);
    deref_impl!(<N> Foo for Box<N> where N: Foo + ?Sized);
    deref_impl!(<N> Foo for std::rc::Rc<N> where N: Foo + ?Sized);
    deref_impl!(<N> Foo for std::sync::Arc<N> where N: Foo + ?Sized);