Operator overloading by value results in use of moved value

ぐ巨炮叔叔 提交于 2019-12-05 06:56:44

If you don't want to copy then, as far as my newbie understanding goes, you need to implement Add on references to Point.

This would be supported by the RFC:

Fortunately, there is no loss in expressiveness, since you can always implement the trait on reference types. However, for types that do need to be taken by reference, there is a slight loss in ergonomics since you may need to explicitly borrow the operands with &. The upside is that the ownership semantics become clearer: they more closely resemble normal function arguments.

And indeed it seems to work:

use std::ops::{Add};

#[derive(Show)]
struct Point {
    x: i32,
    y: i32
}

impl<'a> Add for &'a Point {
    type Output = Point;

    fn add(self, other: &'a Point) -> Point { //'
        Point {x: self.x + other.x, y: self.y + other.y}
    }
}

fn main() {
    let p: Point = Point {x: 1, y: 0};
    let pp = &p + &p;
    println!("{:?}", pp);
}

(playpen)

To make Point copyable instead, just replace #[derive(Show)] with #[derive(Show,Copy)]. Such structs used to be copyable by default, but it changed.

If your structure can't be copied (e.g. it has Drop implementation, either itself or for one of its fields), then it may make sense to create several implementations: value+value, value+reference, reference+value and reference+reference. The first three can reuse the storage of one of the operands, and the last one can clone one of the operands and then just delegate to the already existing implementations. This way the user of your library can easily decide whether they want to reuse existing values for optimization or not.

In fact, that's how e.g. BigInt or Complex types are handled.

Your Point, however, can just be made Copy as it is cheap to copy it.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!