我尝试使用特征和运算符重载在Rust中实现C ++样式表达式模板。我一直在试图超载' +'和' *'对于每个表达式模板结构。编译器抱怨Add
和Mul
特征实现:
错误:无法提供在此包中未定义特征和类型的扩展实现
如果我试图实现特征的类型在没有我的包的情况下是可构造的,那么该错误是有意义的,但该类型是必须实现我定义的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);
}
思想?
答案 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}}!
我的建议是将所有操作和值结构包装为通用结构,并为其实现Add
和Mul
。这样,只为包中定义的简单类型实现Add
和Mul
,编译器很满意。
类似的东西:
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);
}