【问题标题】:Implementing Add trait for an enum without moving data在不移动数据的情况下为枚举实现 Add trait
【发布时间】:2021-09-27 12:50:05
【问题描述】:

我正在尝试为解析树之类的东西实现递归枚举。目前我的出发点是这样的:

#[derive(Debug)]
enum Value<T: Add + Copy> {
    Sum(Rc<Value<T>>, Rc<Value<T>>),
    Scalar(T)
}

显然我现在只关心加法,以后会添加其他操作。我想实现Add trait 来启用以下功能:

let x = Value<f32>::Scalar(0.3);
let y = Value<f32>::Scalar(0.3);
let z = x + y;

z 现在应该是 Value&lt;f32&gt;::Sumxy 不应移动。我的问题是如何实现 Add 特征。或者更确切地说是针对哪些类型。我的第一种方法如下所示:

impl<T: Add + Copy> Add for crate::Value<T> {
    type Output = Self;

    fn add(self, other: Value<T>) -> Self {
        ...
    }
}

此解决方案可编译,但数据已移动。如果我尝试将 add 方法的参数更改为引用,则会失败,因为签名与预期的不匹配。有道理,所以我尝试为&amp;Value&lt;T&gt; 实现特征。这似乎可行,但我不能再写x + y,因为它们不是参考。我也很纠结返回类型,因为它不能是&amp;Value&lt;T&gt;,而必须是Value&lt;T&gt;

我采取了另一种方法来完全使用Rc&lt;Value&lt;T&gt;&gt;,但我不允许为Rc&lt;...&gt; 实现Add。我知道有一个 AsRef 特征,但我对 Rust 很陌生,现在知道它如何适合我的用例。

任何提示如何将这些部分组合在一起并让它们工作将非常感激。

【问题讨论】:

    标签: rust


    【解决方案1】:

    你快到了,你可以用Rc 保持你的方法,但用你自己的类型包装它:

    use std::rc::Rc;
    use std::ops::Add;
    
    #[derive(Debug, Clone)]
    struct WrapperValue<T: Add + Copy>(Rc<Value<T>>);
    
    #[derive(Debug)]
    enum Value<T: Add + Copy> {
        Sum(WrapperValue<T>, WrapperValue<T>),
        Scalar(T)
    }
    
    impl<T: Add + Copy> Add for WrapperValue<T> {
        type Output = WrapperValue<T>;
    
        fn add(self, other: WrapperValue<T>) -> Self {
            WrapperValue(Rc::new(Value::Sum(self.clone(), other.clone())))
        }
    }
    

    Playground

    正如你提到的你不想移动值,你也可以为&amp;实现它:

    impl<T: Add + Copy> Add for &WrapperValue<T> {
        type Output = WrapperValue<T>;
    
        fn add(self, other: &WrapperValue<T>) -> Self::Output {
            WrapperValue(Rc::new(Value::Sum(self.clone(), other.clone())))
        }
    }
    

    Playground

    【讨论】:

    • 这会编译,但是如果我创建两个 WrapperValue 实例并通过“+”添加它们,数据仍然会移动。
    • 但是现在你必须写&amp;x + &amp;y。我想写x + y 而不是移动数据。我开始怀疑这是可能的。可能适用于实现 Copy 的类型,但对于 Rc 是不可能的。
    • @Achim afaik 你不能,这是因为特征本身的界限。我认为你必须选择:(
    猜你喜欢
    • 2014-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    • 1970-01-01
    • 2017-02-18
    • 1970-01-01
    相关资源
    最近更新 更多