在泛型函数中使用泛型类型时如何编写操作?

时间:2019-04-12 01:50:46

标签: generics rust

我正在尝试为定义为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必须实现AddMul特征。 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 ++背景),因此任何反馈将不胜感激。

0 个答案:

没有答案