简体   繁体   English

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

[英]Overloading an operator for all structs with a trait in Rust

I'm trying to implement C++-style expression templates in Rust using traits and operator overloading.我正在尝试使用特征和运算符重载在 Rust 中实现 C++ 风格的表达式模板。 I'm getting stuck trying to overload '+' and '*' for every expression template struct.我在尝试为每个表达式模板结构重载 '+' 和 '*' 时陷入困境。 The compiler complains about the Add and Mul trait implementations:编译器抱怨AddMul trait 实现:

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

That error would make sense if the type I was trying to implement a trait for was constructible without my crate, but the type is a generic that must implement the HasValue trait I defined.如果我尝试为其实现特征的类型无需我的 crate 即可构造,那么该错误是有意义的,但该类型是必须实现我定义的HasValue特征的泛型。

Here's the code:这是代码:

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);
}

Thoughts?想法?

Trying to define the trait Add for you custom types, you are doing this:尝试为您的自定义类型定义特征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,
        }
    }
}

But T: HasValue + Copy matches any type implementing trait HasValue , and this type may not be defined in your crate (for example if you implement HasValue for i32 ).但是T: HasValue + Copy匹配任何实现 trait HasValue类型,并且这个类型可能没有在你的箱子中定义(例如,如果你为i32实现HasValue )。 As Add isn't defined in your crate either, Rust complains: for example by defining HasValue for i32 , you would also re-define Add<i32> for i32 !由于Add未在箱子定义要么,防锈抱怨:例如通过定义HasValuei32 ,也将重新定义Add<i32>i32

My suggestion would be to wrap all your operation and values structs into a generic one, and implementing Add and Mul for it.我的建议是将所有操作和值结构包装成一个通用结构,并为其实现AddMul This way, you implement Add and Mul only for a simple type defined in your crate, and the compiler is happy.这样,您只为在 crate 中定义的简单类型实现AddMul ,编译器很高兴。

Something like that:类似的东西:

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

Then you can just add a neat new() method for your Val type:然后你可以为你的Val类型添加一个简洁的new()方法:

impl Val {
    fn new(n: i32) -> Calculus<Val> {
        Calculus {
            calc: Val { value: n },
        }
    }
}

and use the whole thing like this:并像这样使用整个东西:

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);
}

Playground 操场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 没有从实现 Rust 中的特征的结构推断出特征? - No trait inferred from structs that implement a trait in Rust? Rust? 运算符不适用于 Into<t> 特征</t> - Rust ? operator does not work with Into<T> trait 通过重载运算符用于 Any 的 Rust 管道运算符 - Rust pipeline operator for Any by overloading operators 使用特征和泛型函数在rust中重载函数是否有不利之处? - Is there any downside to overloading functions in rust using a trait & generic function? 如何在特征中使用枚举并在枚举中的结构上实现特征? Rust - How can I use enum in a trait and implement trait on structs that are in the enum? Rust 如何在不使用 ops::Add 特征的情况下重载运算符? - How to overloading operator without using ops::Add trait? 如何在 Rust 中为值和引用实现惯用的运算符重载? - How to implement idiomatic operator overloading for values and references in Rust? 如何在 Rust 中定义 Vec 以支持包含实现相同特征的多种类型的结构? - How to define a Vec in Rust to support containing multiple types of structs that implement a same trait? Rust是否具有所有实体“继承”或实现的类型或特征? - Does Rust have a type or trait that all entities “inherit” or implement? 将所有变体实现相同特征的枚举转换为Rust中的框? - Converting an enum where all variants implement the same trait to a box in Rust?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM