我有以下代码:

use std::ops::Div;
use std::ops::Mul;

#[derive(Debug)]
struct Foo<T> {
    bar: T,
}

impl<T> Foo<T>
where
    T: Div<Output = T> + Copy,
{
    fn new(bar: T) -> Foo<T> {
        let baz = Foo::baz(bar);
        Foo { bar: bar / baz }
    }
    fn baz(bar: T) -> T {
        unimplemented!();
    }
}

impl<T> Mul for Foo<T>
where
    T: Mul<Output = T>,
{
    type Output = Foo<T>;

    fn mul(self, other: Foo<T>) -> Foo<T> {
        Foo::new(self.bar * other.bar)
    }
}

但是,编译器提示:

error[E0277]: cannot divide `T` by `T`
  --> src/main.rs:29:9
   |
29 |         Foo::new(self.bar * other.bar)
   |         ^^^^^^^^ no implementation for `T / T`
   |
   = help: the trait `std::ops::Div` is not implemented for `T`
   = help: consider adding a `where T: std::ops::Div` bound
note: required by `<Foo<T>>::new`
  --> src/main.rs:13:5
   |
13 |     fn new(bar: T) -> Foo<T> {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
  --> src/main.rs:29:9
   |
29 |         Foo::new(self.bar * other.bar)
   |         ^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
   |
   = help: consider adding a `where T: std::marker::Copy` bound
note: required by `<Foo<T>>::new`
  --> src/main.rs:13:5
   |
13 |     fn new(bar: T) -> Foo<T> {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^

可以通过以下修改来解决:
impl<T> Mul for Foo<T>
where
    T: Mul<Output = T> + Div<Output = T> + Copy,

为什么我需要在Div<Output = T>中添加CopyMul for Foo<T>Foo<T>不应该因为以下原因而满足界限:
impl<T> Foo<T>
where
    T: Div<Output = T> + Copy,

最佳答案

每个impl块都完全不同,包括它们的特征范围-一个impl块具有约束这一事实对其他人没有任何意义。

在这种情况下,特征implMul块实际上并不需要Div特征,因为它可以直接构造Foo:

impl<T> Mul for Foo<T>
where
    T: Mul<Output = T>,
{
    type Output = Foo<T>;

    fn mul(self, other: Foo<T>) -> Foo<T> {
        Foo { bar: self.bar * other.bar }
    }
}

只是因为您选择了调用Foo::new(具有DivCopy要求),原始版本的Mul将无法编译。从概念上讲,这是与此简单函数相同的问题,该简单函数也不需要CopyDiv:
fn x<T>(a: T) -> Foo<T> {
    Foo::new(a)
}

请注意,我说的是“impl块”,而不是“固有impl块”或“特征impl块”。您可以具有多个具有不同界限的固有impl块:
impl<T> Vec<T> {
    pub fn new() -> Vec<T> { /* ... */ }
}

impl<T> Vec<T>
where
    T: Clone,
{
    pub fn resize(&mut self, new_len: usize, value: T) { /* ... */ }
}

这使类型具有仅在满足某些条件时才适用的功能。

也可以看看:
  • Is it better to specify trait bound on the impl block or on the method?
  • Should trait bounds be duplicated in struct and impl?
  • Why does Rust require generic type declarations after the "impl" keyword?
  • 关于generics - 如果已经将特征边界添加到另一个impl块,为什么还要在其上添加特征边界?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49673330/

    10-12 07:27