当实现一个基本的固定大小向量类型(例如float2
)时,我想支持Add
和Sub
特性。稍后,我还想支持Mul
和*Assign
。
查阅文档和其他例子后,我得到了以下结果:
use std::ops::{Add, Sub};
#[derive(Copy, Clone)]
struct float2(f64, f64);
impl Add for float2 {
type Output = float2;
fn add(self, _rhs: float2) -> float2 {
float2(self.0 + _rhs.0, self.1 + _rhs.1)
}
}
impl Sub for float2 {
type Output = float2;
fn sub(self, _rhs: float2) -> float2 {
float2(self.0 - _rhs.0, self.1 - _rhs.1)
}
}
这对于基本示例有效,但是我在实践中发现我经常会将引用作为参数传递以及栈上的本地float2
。
为了混合这些,我需要:
- 取消引用变量(可以,但使代码略微难以阅读)。
- 声明操作符重载组合的引用。
示例:
impl<'a, 'b> Add<&'b float2> for &'a float2 {
type Output = float2;
fn add(self, _rhs: &'b float2) -> float2 {
float2(self.0 + _rhs.0, self.1 + _rhs.1)
}
}
impl<'a> Add<float2> for &'a float2 {
type Output = float2;
fn add(self, _rhs: float2) -> float2 {
float2(self.0 + _rhs.0, self.1 + _rhs.1)
}
}
impl<'b> Add<&'b float2> for float2 {
type Output = float2;
fn add(self, _rhs: &'b float2) -> float2 {
float2(self.0 + _rhs.0, self.1 + _rhs.1)
}
}
/*... and again for Sub */
虽然这样可以编写没有解引用的表达式,但是在列举每个组合时变得非常繁琐,特别是添加更多操作和类型(float3
,float4
等)。
是否有一种普遍接受的方法来自动强制转换运算符重载的类型?
使用宏或语言的其他功能来避免繁琐的重复操作?
还是开发人员需要明确地根据需要访问变量作为引用或解引用,并编写大量重复的运算符重载函数?
注意,我目前是初学者,我检查了一些相当高级的Rust数学库,它们超出了我的水平,虽然我可以使用它们 - 但是我想知道如何为自己的类型编写运算符重载。
std::ops
导入forward_ref_binop
吗?还是必须重新定义宏? - Aratzforward_ref
提供了forward_ref_binop
、forward_ref_op_assign
和forward_ref_unop
宏,虽然它们与核心中的宏相比较简化。 - RedGlyph