Std::ops four arithmetic operations requires owned value

assume there's some type that can't easily be cloned

code above doesn't works because Add operation involves moving of lhs and rhs

implementing Add on &T might work a bit tho but adding reference looks weird

using ref for everything looks less weird at least

i don't think Add usually has anything to do with consuming lhs and rhs

and it willl be fine in most case even if it just receive these as reference instead

Could you post the screenshots as text? Images are hard for us to work with. We can't easily copy and paste the code to try it out and make changes.

If you're suggesting changes to the core Add trait this is the right place, but if you're just asking how to write Rust code the Users forum would be a better place to ask. The Internals forum is for discussing changes to the Rust language itself. Compiler changes, new syntax, standard library additions, etc.

3 Likes

By the way, this is nothing that can be changed anyways. Also historically, pre Rust-1.0, these operations were actually changed the other way, from taking references to taking their arguments by-value.

https://rust-lang.github.io/rfcs/0439-cmp-ops-reform.html

Making these traits work by value is motivated by cases like DList concatenation, where you may want the operator to actually consume the operands in producing its output (by welding the two lists together).

It also means that the compiler does not have to introduce a silent & for the operands, which means that the ownership semantics when using these operators is much more clear.

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.

DList seems to be an old name for LinkedList.

6 Likes

For cases where we don't want to consume the operands we can impl for Add for a reference

use core::ops::Add;

struct BigUint {
    bytes: Vec<u32>,
}

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

    fn add(self, with: Self) -> Self::Output {
        /* do addition */
        
        todo!()
    }
}

impl BigUint {
    fn new(str: &str) -> Self {
        todo!()
    } 
}

fn main() {
    let a = BigUint::new("4589765845678654678");
    let b = BigUint::new("8846845334876313843");

    let c = &a + &b;
}

Which makes the current interface more flexible since we can both take by value or take by move.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.