Operator overloading problem

Hi!

Here is an operator overloading example.

use std::ops::Add;

struct MyData {
    data: Vec<f32>,
}

impl Add<MyData> for MyData {
    type Output = MyData;
    fn add(self, d: MyData) -> Self::Output {
        MyData {
            data: self.data.iter().zip(d.data).map(|(x, y)| x + y).collect(),
        }
    }
}

fn main() {
    let a = MyData { data: vec![0.1; 10] };
    let b = MyData { data: vec![0.2; 10] };
    let c = MyData { data: vec![1.0; 10] };

    let r1 = a + b;
    println!("{:?}", r1.data);

    // The problem ...
    let _r2 = a + c;
}

But I have problem with ownership. How should I modify this example?

I assume the problem you're having is that you've moved values into add(), because you're passing by value instead of reference. Thus, a gets moved into oblivion on the first addition with let r1 = a + b;

You have a couple options:

  1. You could implement Copy for MyData with #[derive(Copy)]
  2. You could add impl<'a> Add<&'a MyData> for &'a MyData { ... }, which uses a borrow instead of a move
2 Likes

You cannot do that. The Copy trait cannot be "derived" the same way Clone can be. Or to be more specific, a type is inherently Copy. The derive is required for types which are already Copy (and this is required because some types "appear" to be copyable but additional semantics prevent that), but just slapping a derive on a type that isn't inherently Copy won't make it such.
There is a little reference on the docs page for Copy on when you can and can't have Copy.
TLDR: You cannot "make" a type Copy.

Ok fair point. If you switch the Vec to a plain array, you can derive Copy: Rust Playground

Copy is a bit nicer than Clone for examples like this because it's just a straight byte to byte copy. Vec is heap-based, so Clone makes a bit more sense than Copy. When I think of Copy, I think shallow copy, whereas Clone is more like a deep copy.

Yes, and that's because there is a Copy implementation for [T; N] when T itself is Copy.

I don't think "niceness" was the point here at all. I am guessing you are thinking from a book author's point of view, but I don't think that's what OP wanted here.

Copy makes no sense at all for a Vec. Not sure if you meant something else though.

That is the semantics roughly, although there is no real way for the compiler to verify this semantic. It is suggested here in the docs.

FWIW there's also copy_from_slice(), which is somewhat equivalent to the Copy trait for Vec or a slice, but only for T where T is Copy.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.