Rust 实现可在不同所有权类型上重用的通用代码的最佳实践是什么:&';T形或长方体<;T>;,还是A:T?

Rust 实现可在不同所有权类型上重用的通用代码的最佳实践是什么:&';T形或长方体<;T>;,还是A:T?,rust,Rust,我有一个特点T。我正在实现一个structS,它拥有或保留对实现traitT的对象的引用。可以通过以下几种方式之一实现: 这可能有点依赖于大小写,但如果可能,您应该更喜欢直接获取值(例如,someT:Trait) 还有一个类似的API指南(),建议接口直接获取参数T,而不是对实现std::io::Read或std::io::Write的值的可变引用。这是因为Read和Write也实现了对实现这些特性的任意T类型的可变引用 如果您能够控制这种特性,那么遵循相同的方法是非常惯用的,并且可以解决您的问

我有一个特点
T
。我正在实现一个struct
S
,它拥有或保留对实现trait
T
的对象的引用。可以通过以下几种方式之一实现:


  • 这可能有点依赖于大小写,但如果可能,您应该更喜欢直接获取值(例如,some
    T:Trait

    还有一个类似的API指南(),建议接口直接获取参数
    T
    ,而不是对实现
    std::io::Read
    std::io::Write
    的值的可变引用。这是因为
    Read
    Write
    也实现了对实现这些特性的任意
    T
    类型的可变引用

    如果您能够控制这种特性,那么遵循相同的方法是非常惯用的,并且可以解决您的问题,而不需要太多的构造函数

    trait T { }
    // generic implementations for references and smart container types follow
    impl<'a, U: ?Sized + T> T for &'a U { }
    impl<U: ?Sized + T> T for Box<U> { }
    
    struct A { }
    impl T for A { }
    
    fn main() {
        let a = A {};
        let s1 = S::new(a);
        let s2 = S::new(&a);
        let s3 = S::new(&a as &T);
        let s4 = S::new(Box::new(a));
    }
    
    trait T{}
    //引用和智能容器类型的通用实现如下
    
    感谢您深思熟虑的回答和API指南的链接——这是一本很好的读物。我是否正确地理解了,如果我添加
    implOne进一步的问题:如果&'a U和Box的派生trait实现是有用的,为什么它们不能由编译器自动生成?除了编译时间之外,还有什么缺点吗?@OlegEterevsky从
    S
    的角度来看,它将接受任何类型参数,只要它实现了trait。当该类型有生存期时,编译器将跟踪它。@OlegEterevsky并非所有特征都应该在引用类型上具有继承行为。例如,具有消费方法的特征(按价值衡量自我)就是如此。
    struct S<A: T, 'a> {
        field: &'a A,
    }
    
    struct S<'a> {
        field: &'a T,
    }
    
    struct S {
        field: Box<T>,
    }
    
    trait T { }
    struct A { }
    impl T for A { }
    
    fn main() {
        let a = A {};
        let s1 = S::new_owning(a);
        let s2 = S::new_from_ref(&a);
        let s3 = S::new_from_trait_ref(&a as &T);
        let s4 = S::new_from_boxed_trait(Box::new(a));
    }
    
    trait T { }
    // generic implementations for references and smart container types follow
    impl<'a, U: ?Sized + T> T for &'a U { }
    impl<U: ?Sized + T> T for Box<U> { }
    
    struct A { }
    impl T for A { }
    
    fn main() {
        let a = A {};
        let s1 = S::new(a);
        let s2 = S::new(&a);
        let s3 = S::new(&a as &T);
        let s4 = S::new(Box::new(a));
    }