简体   繁体   English

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

[英]How do I provide an implementation of a generic struct in Rust?

I have a struct MyStruct that takes a generic parameter T: SomeTrait , and I want to implement a new method for MyStruct . 我有一个结构MyStruct ,它采用通用参数T: SomeTrait ,我想为MyStruct实现一个new方法。 This works: 这有效:

/// 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() {}

I wanted to put the new function inside an impl block like this: 我想把new函数放在这样的impl块中:

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

But that fails to compile with: 但是无法编译:

error[E0107]: wrong number of type arguments: expected 1, found 0
 --> src/main.rs:9:6
  |
9 | impl MyStruct {
  |      ^^^^^^^^ expected 1 type argument

If I try to put it like this: 如果我试着这样说:

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

The error changes to: 错误更改为:

error[E0412]: cannot find type `T` in this scope
 --> src/main.rs:9:15
  |
9 | impl MyStruct<T> {
  |               ^ not found in this scope

How do I provide an implementation of a generic struct? 如何提供通用结构的实现? Where do I put the generic parameters and their constraints? 我在哪里放置通用参数及其约束?

The type parameter <T: SomeTrait> should come right after the impl keyword: 类型参数<T: SomeTrait>应该在impl关键字后面:

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

If the list of types and constraints in impl<...> becomes too long, you can use the where -syntax and list the constraints separately: 如果impl<...>中的类型和约束impl<...>变得太长,您可以使用where -syntax并分别列出约束:

impl<T> MyStruct<T>
where
    T: SomeTrait,
{
    fn new(t: T) -> Self {
        MyStruct { value: t }
    }
}

Note the usage of Self , which is a shortcut for MyStruct<T> available inside of the impl block. 请注意Self的用法,它是impl块内部可用的MyStruct<T>的快捷方式。


Remarks 备注

  1. The reason why impl<T> is required is explained in this answer . 本答案解释了impl<T>的原因。 Essentially, it boils down to the fact that both impl<T> MyStruct<T> and impl MyStruct<T> are valid, but mean different things. 从本质上讲,它归结为impl<T> MyStruct<T>impl MyStruct<T>都有效,但意味着不同的事实。

  2. When you move new into the impl block, you should remove the superfluous type parameters, otherwise the interface of your struct will become unusable, as the following example shows: 当您将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. } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM