我试着写两个特征,其中一个需要另一个实现并得到这个错误:
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)
这听起来像你想ValTrait成为一个supertrait的ValRequireTrait。可以在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)