如何提供拉斯特的通用结构的实现?

问题描述 投票:3回答:1

我有一个结构MyStruct,需要一个通用的参数T: SomeTrait,我想实施new一个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() {}

我希望把new功能像这样的impl块中:

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

但是,失败,编译:

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<T> {
    fn new(t: T) -> MyStruct<T> {
        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

如何提供一个通用结构的实现?我应该把通用参数及其制约因素?

generics struct rust
1个回答
3
投票

<T: SomeTrait>关键字之后的类型参数impl应该来:

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

如果类型和约束在impl<...>列表变得太长,你可以使用where语法和单独列出的限制:

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

注意Self的使用,这是可用的MyStruct<T>块内impl的快捷方式。


备注

  1. 为什么需要impl<T>的原因是this answer解释。本质上,它归结为一个事实,即impl<T> MyStruct<T>impl MyStruct<T>是有效的,但意味着不同的事情。
  2. 当您移动newimpl块,你应该删除多余的类型参数,否则你的结构的界面将变得不可用,如下例所示: // 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. }
© www.soinside.com 2019 - 2024. All rights reserved.