Generics 如何在Rust中提供通用结构的实现?

Generics 如何在Rust中提供通用结构的实现?,generics,struct,rust,Generics,Struct,Rust,我有一个结构MyStruct,它接受一个通用参数T:SomeTrait,我想为MyStruct实现一个新的方法。这项工作: /// Constraint for the type parameter `T` in MyStruct pub trait SomeTrait: Clone {} /// The struct that I want to construct with `new` pub struct MyStruct<T: SomeTrait> { value:

我有一个结构
MyStruct
,它接受一个通用参数
T:SomeTrait
,我想为
MyStruct
实现一个新的
方法。这项工作:

/// Constraint for the type parameter `T` in MyStruct
pub trait SomeTrait: Clone {}

/// The struct that I want to construct with `new`
pub struct MyStruct<T: SomeTrait> {
    value: T,
}

fn new<T: SomeTrait>(t: T) -> MyStruct<T> {
    MyStruct { value: t }
}

fn main() {}
但这无法通过以下方式编译:

error[E0107]: wrong number of type arguments: expected 1, found 0
 --> src/main.rs:9:6
  |
9 | impl MyStruct {
  |      ^^^^^^^^ expected 1 type argument
如果我试着这样说:

impl MyStruct {
    fn new<T: SomeTrait>(t: T) -> MyStruct<T> {
        MyStruct { value: t }
    }
}
impl MyStruct<T> {
    fn new(t: T) -> MyStruct<T> {
        MyStruct { value: t }
    }
}
impl MyStruct{
fn new(t:t)->MyStruct{
MyStruct{value:t}
}
}
错误更改为:

error[E0412]: cannot find type `T` in this scope
 --> src/main.rs:9:15
  |
9 | impl MyStruct<T> {
  |               ^ not found in this scope
错误[E0412]:在此作用域中找不到类型'T'
-->src/main.rs:9:15
|
9 |实施我的结构{
|^在此范围内找不到
如何提供泛型结构的实现?将泛型参数及其约束放在何处?

类型参数
应紧跟在
impl
关键字之后:

impl<T: SomeTrait> MyStruct<T> {
    fn new(t: T) -> Self {
        MyStruct { value: t }
    }
}
请注意
Self
的用法,它是
impl
块中可用的
MyStruct
的快捷方式


备注

  • 需要
    impl
    的原因在中进行了解释。从本质上讲,这归结为
    impl MyStruct
    impl MyStruct
    都是有效的,但含义不同

  • new
    移动到
    impl
    块时,应删除多余的类型参数,否则结构的接口将变得不可用,如下例所示:

    // trait SomeTrait and struct MyStruct as above
    // [...]
    
    impl<T> MyStruct<T>
    where
        T: SomeTrait,
    {
        fn new<S: SomeTrait>(t: S) -> MyStruct<S> {
            MyStruct { value: t }
        }
    }
    
    impl SomeTrait for u64 {}
    impl SomeTrait for u128 {}
    
    fn main() {
        // just a demo of problematic code, don't do this!
        let a: MyStruct<u128> = MyStruct::<u64>::new::<u128>(1234);
        //                                 ^
        //                                 |
        //        This is an irrelevant type
        //        that cannot be inferred. Not only will the compiler
        //        force you to provide an irrelevant type, it will also
        //        not prevent you from passing incoherent junk as type
        //        argument, as this example demonstrates. This happens 
        //        because `S` and `T` are completely unrelated.
    }
    
    //trait SomeTrait和struct MyStruct如上所述
    // [...]
    impl MyStruct
    哪里
    T:某种特质,
    {
    fn新(t:S)->MyStruct{
    MyStruct{value:t}
    }
    }
    u64{}的impl SomeTrait
    u128{}的impl SomeTrait
    fn main(){
    //只是一个有问题代码的演示,不要这样做!
    设a:MyStruct=MyStruct:::new::(1234);
    //                                 ^
    //                                 |
    //这是一种不相关的类型
    //这是无法推断的。不仅编译器
    //强制您提供一个不相关的类型,它也会
    //不阻止您将不连贯的垃圾作为类型传递
    //参数,如本例所示。这种情况会发生
    //因为'S'和'T'完全不相关。
    }
    

  • @AndreyTyukin我刚刚找到了你的答案,正在阅读std::rc::rc in的代码。如果你创建了答案,我会很乐意标记它。这不是一个拼写错误;我只是不知道“impl”会起作用。好的。我也投票关闭了。如果你在答案中添加链接可能是最好的,这样它就不会在这些短暂的评论中丢失。回答很好。比ks提供了详细的解释和清晰的示例。
    // trait SomeTrait and struct MyStruct as above
    // [...]
    
    impl<T> MyStruct<T>
    where
        T: SomeTrait,
    {
        fn new<S: SomeTrait>(t: S) -> MyStruct<S> {
            MyStruct { value: t }
        }
    }
    
    impl SomeTrait for u64 {}
    impl SomeTrait for u128 {}
    
    fn main() {
        // just a demo of problematic code, don't do this!
        let a: MyStruct<u128> = MyStruct::<u64>::new::<u128>(1234);
        //                                 ^
        //                                 |
        //        This is an irrelevant type
        //        that cannot be inferred. Not only will the compiler
        //        force you to provide an irrelevant type, it will also
        //        not prevent you from passing incoherent junk as type
        //        argument, as this example demonstrates. This happens 
        //        because `S` and `T` are completely unrelated.
    }