我正在尝试使用traits和运算符重载在Rust中实现C++样式表达式模板.我试图为每个表达式模板结构重载'+'和'*'.编译器抱怨Add和Multrait实现:
错误:无法提供扩展实现,其中特征和类型都未在此包中定义
如果我试图实现特征的类型在没有我的包的情况下是可构造的,那么该错误将是有意义的,但该类型是必须实现HasValue我定义的特征的泛型.
这是代码:
trait HasValue {
    fn get_value(&self) -> int;
}
// Val
struct Val {
  value: int
}
impl HasValue for Val {
  fn get_value(&self) -> int {
    self.value
  }
}
// Add
struct AddOp<T1: HasValue + Copy, T2: HasValue + Copy> {
    lhs: T1,
    rhs: T2
}
impl<T1: HasValue + Copy, T2: HasValue + Copy> HasValue for AddOp<T1, T2> {
  fn get_value(&self) -> int {
    self.lhs.get_value() + self.rhs.get_value()
  }
}
impl<T: HasValue + Copy, O: HasValue + Copy> Add<O, AddOp<T, O>> for T {
  fn add(&self, other : &O) -> AddOp<T, O> {
    AddOp { lhs: *self, rhs: *other }
  }
}
// Mul
struct MulOp<T1: HasValue + Copy, T2: HasValue + Copy> {
    lhs: T1,
    rhs: T2
}
impl<T1: HasValue + Copy, T2: HasValue + Copy> HasValue for MulOp<T1, T2> {
  fn get_value(&self) -> int {
    self.lhs.get_value() * self.rhs.get_value()
  }
}
impl<T: HasValue + Copy, O: HasValue + Copy> Mul<O, MulOp<T, O>> for T {
  fn mul(&self, other : &O) -> MulOp<T, O> {
    MulOp { lhs: *self, rhs: *other }
  }
}
fn main() {
  let a = Val { value: 1 };
  let b = Val { value: 2 };
  let c = Val { value: 2 };
  let e = ((a + b) * c).get_value();
  print!("{}", e);
}
思考?
尝试为您的自定义类型定义特征Add,您正在这样做:
impl<T: HasValue + Copy, O: HasValue + Copy> Add<O> for T {
    type Output = AddOp<T, O>;
    fn add(&self, other: &O) -> AddOp<T, O> {
        AddOp {
            lhs: *self,
            rhs: *other,
        }
    }
}
但T: HasValue + Copy匹配任何实现 Trait 的类型HasValue,并且该类型可能未在您的包中定义(例如,如果您实现HasValuefor i32)。由于Add您的板条箱中也没有定义,Rust 抱怨道:例如,通过定义HasValuefor i32,您还可以重新定义Add<i32>for i32!
我的建议是将所有操作和值结构包装到一个通用结构中,并为其实现Add和。Mul这样,您就可以实现Add并且Mul仅针对您的包中定义的简单类型,并且编译器会很高兴。
像这样的东西:
struct Calculus<T> {
    calc: T,
}
impl<T: HasValue + Copy> HasValue for Calculus<T> {
    fn get_value(&self) -> i32 {
        self.calc.get_value()
    }
}
impl<T, O> Add<Calculus<O>> for Calculus<T>
where
    T: HasValue + Copy,
    O: HasValue + Copy,
{
    type Output = Calculus<AddOp<T, O>>;
    fn add(self, other: Calculus<O>) -> Calculus<AddOp<T, O>> {
        Calculus {
            calc: AddOp {
                lhs: self.calc,
                rhs: other.calc,
            },
        }
    }
}
impl<T, O> Mul<Calculus<O>> for Calculus<T>
where
    T: HasValue + Copy,
    O: HasValue + Copy,
{
    type Output = Calculus<MulOp<T, O>>;
    fn mul(self, other: Calculus<O>) -> Calculus<MulOp<T, O>> {
        Calculus {
            calc: MulOp {
                lhs: self.calc,
                rhs: other.calc,
            },
        }
    }
}
然后你可以为你的类型添加一个简洁的new()方法Val:
impl Val {
    fn new(n: i32) -> Calculus<Val> {
        Calculus {
            calc: Val { value: n },
        }
    }
}
并像这样使用整个事情:
fn main() {
    let a = Val::new(1);
    let b = Val::new(2);
    let c = Val::new(3);
    let e = ((a + b) * c).get_value();
    print!("{}", e);
}