我正在尝试使用traits和运算符重载在Rust中实现C++样式表达式模板.我试图为每个表达式模板结构重载'+'和'*'.编译器抱怨Add
和Mul
trait实现:
错误:无法提供扩展实现,其中特征和类型都未在此包中定义
如果我试图实现特征的类型在没有我的包的情况下是可构造的,那么该错误将是有意义的,但该类型是必须实现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)
思考?
尝试为您的自定义类型定义特征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
,并且该类型可能未在您的包中定义(例如,如果您实现HasValue
for i32
)。由于Add
您的板条箱中也没有定义,Rust 抱怨道:例如,通过定义HasValue
for 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)
归档时间: |
|
查看次数: |
788 次 |
最近记录: |