当前位置: 首页 > 知识库问答 >
问题:

重载具有Rust特征的所有结构的运算符

澹台举
2023-03-14

我试图在Rust中实现C风格的表达式模板,使用特性和运算符重载。我试图重载每个表达式模板结构的'和'*'。编译器抱怨AddMul特性实现:

error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
  --> src/main.rs:32:6
   |
32 | impl<T: HasValue + Copy, O: HasValue + Copy> Add<O> for T {
   |      ^ type parameter `T` must be used as the type parameter for some local type
   |
   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
   = note: only traits defined in the current crate can be implemented for a type parameter

如果我试图为其实现特征的类型在没有我的板条箱的情况下是可构造的,但该类型是必须实现我定义的HasValue特征的泛型,则该错误是有意义的。

代码如下:

use std::ops::{Add, Mul};

trait HasValue {
    fn get_value(&self) -> i32;
}

// Val

struct Val {
    value: i32,
}

impl HasValue for Val {
    fn get_value(&self) -> i32 {
        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) -> i32 {
        self.lhs.get_value() + self.rhs.get_value()
    }
}

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,
        }
    }
}

// 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) -> i32 {
        self.lhs.get_value() * self.rhs.get_value()
    }
}

impl<T: HasValue + Copy, O: HasValue + Copy> Mul<O> for T {
    type Output = MulOp<T, O>;
    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);
}

想法?

共有1个答案

厉高逸
2023-03-14

试图为自定义类型定义traitAdd,您正在执行以下操作:

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,
        }
    }
}

但是T:HasValue Copy匹配任何实现trait的类型HasValue,并且此类型可能不会在您的板条箱中定义(例如,如果您为i32实现HasValue)。由于您的板条箱中也没有定义Add,Rust抱怨:例如,通过为i32定义HasValue,您还可以重新定义Add

我的建议是将所有的操作和值结构包装成一个通用结构,并为其实现AddMul。通过这种方式,您只为机箱中定义的简单类型实现了AddMul编译器很高兴。

类似的东西:

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,
            },
        }
    }
}

然后,您可以为您的Val类型添加一个整洁的new()方法:

impl Val {
    fn new(n: i32) -> 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);
}

游戏场

 类似资料:
  • 看看这个代码。 愚蠢的Scala编译器在这里显示错误: 错误:(22, 39) 类型不匹配;找到: mix.type (底层类型 SomeMix) 必需: T with SomeMix 大小写混合: SomeMix = 它不理解表达式I匹配到在某种混合已经是类型T。好吧,让我们帮助他。更改代码: 现在,它同意一切都是正确的,但显示警告: 警告:(22,17)抽象类型模式T未选中,因为它已通过擦除大

  • 我正在尝试制作一个自定义的矢量数据结构。它将始终包含4个浮点值。我想让它通过属性名访问,但也可以通过运算符[],这样它也可以通过索引访问,比如数组。它应该可以通过运算符[]进行编辑,就像向量或数组一样。到目前为止,我已经做到了: 有没有更高雅的方法来解决这个问题呢?

  • 我的情况是,我希望一些对象实现一个特征,比如说“基本”,而其他一些对象将实现一个特征“超级”。Super trait还必须是< code>T : Base的泛型,这样我就可以根据它所专用的Base自动实现Super的各个部分。现在,这似乎可以很好地处理下面的小例子 我的问题与我的下一个要求有关,那就是我希望能够存储实现Super的对象向量,而不管它专门用于哪个Base。我的想法是创建一个涵盖所有超

  • 我需要找到我的集合是否包含相同或超过5个元素的公共变量,并找到这些元素。我这样做: 但是你认为把另一个流放进去过滤是不好的做法。

  • 我想使用斯坦福分类器进行文本分类。我的特征主要是文本特征,但也有一些数字特征(例如句子的长度)。 我从ClassifierExample开始,并用一个简单的实值特性替换当前特性,如果停止灯,则值,否则,这将导致以下代码(除了第10-16行的函数之外,这只是原始ClassifierExample类的代码): 根据我对线性分类器的理解,特性应该使分类任务变得非常容易--毕竟,我们只需要检查的值是否大于