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

Mic*_*yne 7 rust

我正在尝试使用traits和运算符重载在Rust中实现C++样式表达式模板.我试图为每个表达式模板结构重载'+'和'*'.编译器抱怨AddMultrait实现:

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

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

思考?

Lev*_*ans 5

尝试为您的自定义类型定义特征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,
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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,
            },
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以为你的类型添加一个简洁的new()方法Val

impl Val {
    fn new(n: i32) -> Calculus<Val> {
        Calculus {
            calc: Val { value: n },
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用整个事情:

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);
}
Run Code Online (Sandbox Code Playgroud)

操场