代码之家  ›  专栏  ›  技术社区  ›  Jeffrey

如何在不移出参数的情况下实现std::ops:add、sub、mul、div运算符之一?

  •  1
  • Jeffrey  · 技术社区  · 6 年前

    我正在写一个光线跟踪器,我想能够减去我的三维向量:

    use std::ops::Sub;
    
    #[derive(Clone, Debug)]
    pub struct Vec3 {
        pub v: [f64; 3],
    }
    
    impl Sub for Vec3 {
        type Output = Vec3;
    
        fn sub(self, other: Vec3) -> Vec3 {
            Vec3 {
                v: [
                    self.v[0] - other.v[0],
                    self.v[1] - other.v[1],
                    self.v[2] - other.v[2],
                ],
            }
        }
    }
    

    这似乎奏效了。但是,当我尝试使用它时:

    fn main() {
        let x = Vec3 { v: [0., 0., 0.] };
        let y = Vec3 { v: [0., 0., 0.] };
        let a = x - y;
        let b = x - y;
    }
    

    我收到编者的投诉:

    error[E0382]: use of moved value: `x`
      --> src/main.rs:26:13
       |
    25 |     let a = x - y;
       |             - value moved here
    26 |     let b = x - y;
       |             ^ value used here after move
       |
       = note: move occurs because `x` has type `Vec3`, which does not implement the `Copy` trait
    
    error[E0382]: use of moved value: `y`
      --> src/main.rs:26:17
       |
    25 |     let a = x - y;
       |                 - value moved here
    26 |     let b = x - y;
       |                 ^ value used here after move
       |
       = note: move occurs because `y` has type `Vec3`, which does not implement the `Copy` trait
    

    如何编写减法运算符以使上面的代码工作?

    请不要告诉我应该有一个现有的三维数学模块。我确信还有更好的东西,但我是在学习如何自己去学习语言之后。

    How do I implement the Add trait for a reference to a struct? 没有帮助,因为它需要为我还没有指定的对象指定生命周期。

    1 回复  |  直到 6 年前
        1
  •  4
  •   trent oli_obk    6 年前

    在这个例子中,编译器告诉你为什么 x 已因移动而失效:

       = note: move occurs because `x` has type `Vec3`, which does not implement the `Copy` trait
    

    在这种情况下,您可以简单地添加 #[derive(Copy)] 给予 Vec3 拷贝语义 :

    #[derive(Clone, Copy, Debug)]
    pub struct Vec3 {
        pub v: [f64; 3],
    }
    

    Copy 是一个标记特性,它向编译器指示类型的值在移出时不会变为无效。具有此属性的类型被称为具有复制语义,而不实现的类型 拷贝 据说有移动语义学。 Is it possible to make a type only movable and not copyable? How does Rust provide move semantics? 更详细地解释这个概念。


    但是,您只能实现 拷贝 对于只包含其他 拷贝 类型。如果 VEC3 实际上举行了 Vec 在它内部,编译器不会让您实现 拷贝 为了它。幸运的是,引用确实实现了 拷贝 ,因此您可以改为实现 Sub 对于一个 参考 VEC3 ,使用中描述的方法 How do I implement the Add trait for a reference to a struct?