I made a two element Vector
struct and I want to overload the +
operator.
I made all my functions and methods take references, rather than values, and I want the +
operator to work the same way.
impl Add for Vector { fn add(&self, other: &Vector) -> Vector { Vector { x: self.x + other.x, y: self.y + other.y, } } }
Depending on which variation I try, I either get lifetime problems or type mismatches. Specifically, the &self
argument seems to not get treated as the right type.
I have seen examples with template arguments on impl
as well as Add
, but they just result in different errors.
I found How can an operator be overloaded for different RHS types and return values? but the code in the answer doesn't work even if I put a use std::ops::Mul;
at the top.
I am using rustc 1.0.0-nightly (ed530d7a3 2015-01-16 22:41:16 +0000)
I won't accept "you only have two fields, why use a reference" as an answer; what if I wanted a 100 element struct? I will accept an answer that demonstrates that even with a large struct I should be passing by value, if that is the case (I don't think it is, though.) I am interested in knowing a good rule of thumb for struct size and passing by value vs struct, but that is not the current question.
Implementing a trait in Rust To implement a trait, declare an impl block for the type you want to implement the trait for. The syntax is impl <trait> for <type> . You'll need to implement all the methods that don't have default implementations.
Rust uses a feature called traits, which define a bundle of functions for structs to implement. One benefit of traits is you can use them for typing. You can create functions that can be used by any structs that implement the same trait.
We can return a struct from a function by specifying the struct name as the return type. We can define functions that are specific to a struct, called methods, that can only be used by instances of that struct. A method must be defined inside a impl struct_name code block.
A trait object is an opaque value of another type that implements a set of traits. The set of traits is made up of an object safe base trait plus any number of auto traits. Trait objects implement the base trait, its auto traits, and any supertraits of the base trait.
You need to implement Add
on &Vector
rather than on Vector
.
impl<'a, 'b> Add<&'b Vector> for &'a Vector { type Output = Vector; fn add(self, other: &'b Vector) -> Vector { Vector { x: self.x + other.x, y: self.y + other.y, } } }
In its definition, Add::add
always takes self
by value. But references are types like any other1, so they can implement traits too. When a trait is implemented on a reference type, the type of self
is a reference; the reference is passed by value. Normally, passing by value in Rust implies transferring ownership, but when references are passed by value, they're simply copied (or reborrowed/moved if it's a mutable reference), and that doesn't transfer ownership of the referent (because a reference doesn't own its referent in the first place). Considering all this, it makes sense for Add::add
(and many other operators) to take self
by value: if you need to take ownership of the operands, you can implement Add
on structs/enums directly, and if you don't, you can implement Add
on references.
Here, self
is of type &'a Vector
, because that's the type we're implementing Add
on.
Note that I also specified the RHS
type parameter with a different lifetime to emphasize the fact that the lifetimes of the two input parameters are unrelated.
1 Actually, reference types are special in that you can implement traits for references to types defined in your crate (i.e. if you're allowed to implement a trait for T
, then you're also allowed to implement it for &T
). &mut T
and Box<T>
have the same behavior, but that's not true in general for U<T>
where U
is not defined in the same crate.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With