我尝试编写两个特征,其中一个特征需要实现另一个特征,但收到此错误:
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`
代码:
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);
}
如何正确执行此操作?如果我按照编译器的指示去做,我将不需要
ValRequireTrait
,因为它毫无用处。我希望 ValRequireTrait
成为该结构实现了我需要的足够方法的标志。
换句话说,我希望这样的要求是可传递的,因此当在
get()
函数中我需要一个特征 (ValRequireTrait
) 时,将自动需要其他特征 (ValTrait
),而无需在代码中按照编译器的要求进行任何指定。
听起来您希望
ValTrait
成为 ValRequireTrait
的 超级特质。很好的介绍可以在Rust 书(第 2 版)中找到:
有时,我们可能希望一个特征能够依赖于在我们的特征实现的地方也实现的另一个特征,以便我们的特征可以使用另一个特征的功能。所需的特征是我们正在实现的特征的超特征。
如果更改此行:
trait ValRequireTrait<T: ValTrait = Self> {}
对此,它编译得很好:
trait ValRequireTrait<T: ValTrait = Self>: ValTrait<T> {}
我正在寻找的解决方案是supertraits。
pub trait Foo{
fn hello(&self);
}
pub trait Bar{
fn world(&self);
}
pub trait Baz: Foo + Bar {
fn say_hi(&self){
self.hello()
self.world()
}
}