为Rust中具有特征的所有结构重载运算符

时间:2014-10-22 22:30:13

标签: rust

我尝试使用特征和运算符重载在Rust中实现C ++样式表达式模板。我一直在试图超载' +'和' *'对于每个表达式模板结构。编译器抱怨AddMul特征实现:

  

错误:无法提供在此包中未定义特征和类型的扩展实现

如果我试图实现特征的类型在没有我的包的情况下是可构造的,那么该错误是有意义的,但该类型是必须实现我定义的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);
}

思想?

1 个答案:

答案 0 :(得分:2)

尝试为自定义类型定义特征Add,您这样做:

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 }
  }
}

但是T: HasValue + Copy匹配任何实现特征HasValue的类型,并且您的包中可能未定义此类型(例如,如果您为HasValue实施int)。由于Add未在您的包中定义,Rust会抱怨:例如,为HasValue定义int,您还需要为{{Add重新定义int 1}}!

我的建议是将所有操作和值结构包装为通用结构,并为其实现AddMul。这样,只为包中定义的简单类型实现AddMul,编译器很满意。

类似的东西:

struct Calculus<T: HasValue + Copy> {
    calc: T
}

impl<T: HasValue + Copy> HasValue for Calculus<T> {
    fn get_value(&self) -> int {
        self.calc.get_value()
    }
}

impl<T, O> Add<Calculus<O>, Calculus<AddOp<T, O>>> for Calculus<T>
  where T: HasValue + Copy, O: HasValue + Copy {
  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>, Calculus<MulOp<T, O>>> for Calculus<T>
 where T: HasValue + Copy, O: HasValue + Copy {
  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: int) -> 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);
}