如何正确地要求其他特征的特征?

Vic*_*voy 8 rust

我试着写两个特征,其中一个需要另一个实现并得到这个错误:

error[E0277]: the trait bound `T: ValTrait` is not satisfied
  --> src/main.rs:20:1
   |
20 | / fn get<T: ValRequireTrait + std::fmt::Debug>(_t: T) {
21 | |     println!("{:?}", T::VAL);
22 | | }
   | |_^ the trait `ValTrait` is not implemented for `T`
   |
   = help: consider adding a `where T: ValTrait` bound
   = note: required by `ValRequireTrait`
Run Code Online (Sandbox Code Playgroud)

代码:

trait ValTrait<T = Self> {
    const VAL: T;
}

trait ValRequireTrait<T: ValTrait = Self> {}

#[derive(Debug, Copy, Clone)]
struct A {
    field: u64,
}

impl ValTrait for A {
    const VAL: A = A {
        field: 0u64
    };
}
impl ValRequireTrait for A {}


fn get<T: ValRequireTrait + std::fmt::Debug>(_t: T) {
    println!("{:?}", T::VAL);
}

fn main() {
    let a = A { field: 6u64 };
    get(a);
}
Run Code Online (Sandbox Code Playgroud)

怎么做到这一点?如果我做了编译器所说的我将不需要ValRequireTrait它,因为它将是无用的.我想ValRequireTrait成为一个标记,结构实现了我需要的足够的方法.

换句话说,我希望这样的要求是可传递的,所以当在get()函数中我需要一个trait(ValRequireTrait)时,其他(ValTrait)将自动被要求,而不需要编译器想要的代码中的任何规范.

Pet*_*man 10

我正在寻找的解决方案是supertraits


trait Foo{
  fn hello(&self);
}

trait Bar{
  fn world(&self);
}

trait Baz: Foo + Bar {
  fn say_hi(&self){
    self.hello()
    self.world()
  }
}
Run Code Online (Sandbox Code Playgroud)


Sta*_*iff 8

这听起来像你想ValTrait成为一个supertraitValRequireTrait。可以在Rust 书(第 2 版)中找到一个很好的介绍:

有时,我们可能希望一个 trait 能够依赖在我们的 trait 实现的任何地方也实现的另一个 trait,以便我们的 trait 可以使用另一个 trait 的功能。所需的特征是我们正在实现的特征的超特征。

如果您更改此行:

trait ValRequireTrait<T: ValTrait = Self> {}
Run Code Online (Sandbox Code Playgroud)

对此,它编译得很好:

trait ValRequireTrait<T: ValTrait = Self>: ValTrait<T> {}
Run Code Online (Sandbox Code Playgroud)

  • @VictorPolevoy `ValRequireTrait` 几乎没用,因为它的参数化方式与 `ValTrait` 相同。我怀疑您正在寻找 `trait ValRequireTrait : Sized + ValTrait {}`(`ValRequireTrait` 上没有参数)。[示例](https://play.rust-lang.org/?gist=d1a5cbda10d5b63e6082b8caada49911&amp;version=stable) (3认同)