我正在尝试为定义为Add
的通用Vec3D
类型实现Vec3D<T, U>
特性。 U
用作幻像类型,用于类型安全的目的,例如以确保您永远不能在3D空间中用颜色添加点。
到目前为止,我一直在努力实现Add
特化的Vec3D<T, Color>
特性。下面的代码更详细地说明了我的问题,
use std::marker::PhantomData;
use std::ops::{Add, Mul};
struct Color();
struct Data();
struct Vec3D<T, U>(T, T, T, PhantomData<U>);
// Compiles and runs, but may overflow...
impl<T> Add<Vec3D<T, Data>> for Vec3D<T, Data>
where
T: Add<Output = T>,
{
type Output = Vec3D<T, Data>;
fn add(self, other: Vec3D<T, Data>) -> Vec3D<T, Data> {
Vec3D(
self.0 + other.0,
self.1 + other.1,
self.2 + other.2,
PhantomData,
)
}
}
// Does not work...
impl<T> Add<Vec3D<T, Color>> for Vec3D<T, Color>
where
T: /* what goes here? */,
{
type Output = /* ... */;
fn add(self, other: Vec3D<T, Color>) -> /* ... */ {
Vec3D(
(self.0 + other.0) * 0.5,
(self.1 + other.1) * 0.5,
(self.2 + other.2) * 0.5,
PhantomData,
)
}
}
很明显,类型T
必须实现Add
和Mul
特征。 Add
特征的输出必须与类型T
相同,但是Mul
特征的输出对我来说不太清楚。
我尝试了以下实现,但均未成功(产生类型不匹配错误)
impl<T, U> Add<Vec3D<T, Color>> for Vec3D<T, Color>
where
T: Add<Output = T> + Copy,
<T as Add>::Output: Mul<Output = U>,
{
type Output = Vec3D<U, Color>;
fn add(self, other: Vec3D<T, Color>) -> Vec3D<U, Color> {
Vec3D(
(self.0 + other.0) * 0.5,
(self.1 + other.1) * 0.5,
(self.2 + other.2) * 0.5,
PhantomData,
)
}
}
我知道问题在于乘以0.5
,因为这意味着该操作不再在T
范围内关闭,因此输出可以是完全不同的类型(例如,如果T
是整数类型乘以0.5
可能会产生浮点结果)。解决此问题的直接方法是将所有内容都转换为原始类型,然后进行操作,但是我正在寻找一种不太暴力的方法。
我不知道如何在单个函数中组合这些特征,也不知道我的实现是否被认为是Rust语言的一种不好的做法(我来自C ++背景),因此任何反馈将不胜感激。