如何在不消耗值的情况下实现Add trait

How to implement Add trait without consuming the value

当为简单结构实现 Add 特征(以及其他一些特征,如 MulSub 等)时,必须完全使用结构值,因此以后无法使用它。

同时,内置基元(u8usize 等)实现了 Add,同时允许在调用 add 后使用它。

如何为我的结构实现 Add 以便在调用 add 后能够使用它?

use std::ops::Add;

struct I(usize);
impl Add for I {
    type Output = Self;
    fn add(self, rhs: Self) -> Self {
        I(self.0 + rhs.0)
    }
}

fn main() {
    let a = 123;
    let b = a + a; // no error

    let a1 = I(123);
    let b1 = a1 + a1;

    println!("b={}", b);
}
error[E0382]: use of moved value: `a1`
  --> src/main.rs:16:19
   |
15 |     let a1 = I(123);
   |         -- move occurs because `a1` has type `I`, which does not implement the `Copy` trait
16 |     let b1 = a1 + a1;
   |              --   ^^ value used here after move
   |              |
   |              value moved here

您应该能够将 #[derive(Copy, Clone)] 添加到结构中,然后它不会使用该值,而是使用一个副本。

您可以 impl Deref 并取消引用该值。这将适用于 Add 类型的简单包装类型。

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

struct I(usize);
impl Add for I {
    type Output = Self;
    fn add(self, rhs: Self) -> Self {
        I(self.0 + rhs.0)
    }
}

impl Deref for I {
    type Target = usize;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

fn main() {
    let a = 123;
    let b = a + a; // no error

    let a1 = I(123);

    // Note the dereferences.
    let b1 = *a1 + *a1;

    println!("b={}", b);
}

注意:在这种情况下,Ryan 的回答应该足够了,因为 usize 是克隆类型。