1

I'm new to Swift so please let me know if I've missed something painful obvious. I have a class that I want to pass by value to overload the + operator.

The code won't work if I define the left argument lhs as foo but then it is immutable, and will work if lhs is inout foo, but then I have modified lhs which I clearly do not want.

A quick breakdown of my class:

class foo<T: Numeric> {
    /* Data */
    /* Init Fn */
    /* += definition */
    static func + (lhs: foo, rhs: foo) -> foo {
        do {
            try lhs += rhs
            return lhs
        } catch {
            /* Error Handling */
        }
    }
}

I come from a C++ background, so I am surprised that I am unable to pass the object by value if I choose. Following the question What are the basic rules and idioms for operator overloading?, in C++ this overloading method would expect the left argument to be passed by value and the right argument to be passed by const & as shown below, but here I don't seem to have that option.

class X {
    /* In Swift operators are not defined internally like this */
    X& operator+=(const X& rhs) {
        // actual addition of rhs to *this
        return *this;
    }
};
inline X operator+(X lhs, const X& rhs) {
    lhs += rhs;
    return lhs;
}

Is there a way that I don't know about, or is overloading done differently in Swift?

Any help would be greatly appreciated.

Z4ckZ3r0
  • 113
  • 9
  • You want to do `y += x` without modifying `y`? What would the expected result of such an operation be? – Joakim Danielson Feb 17 '19 at 21:40
  • I want to modify `y` locally in the function rather than modify its reference. – Z4ckZ3r0 Feb 17 '19 at 21:42
  • In C++ you can decide to allocate classes on the stack. In Swift all classes leave in the heap. You just cannot pass a class as a value. I would argue it's C++ with the obscure lvalue & rvalue rules, not Swift. You should start by defining `+=` using `+`, not the other way around. – Sulthan Feb 17 '19 at 21:42
  • I don't understand the question: What are you hoping to achieve by passing an object instance by value? Are you trying to make `+` return a modified copy of `lhs`, rather than mutating the existing instance? – Alexander Feb 17 '19 at 21:56

1 Answers1

2

I don't see any real problem with mutability. Note that with classes, without passing-by-value, you just cannot use one operator to define the other one.

class Foo<T: Numeric> {
    var value: T

    init(value: T) {
        self.value = value
    }

    static func + (lhs: Foo, rhs: Foo) -> Foo {
        return Foo(value: lhs.value + rhs.value)
    }

    static func += (lhs: Foo, rhs: Foo) {
        lhs.value += rhs.value
    }
}

let ten = Foo<Int>(value: 10)
let eighteen = ten + Foo<Int>(value: 8)
eighteen += Foo<Int>(value: 1)
Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • This is what I was looking for, great! In C++, its the other way round: the `+` operator is defined by the `+=` operator, which I guess is why I have been struggling. How strange! – Z4ckZ3r0 Feb 17 '19 at 22:05
  • @Z4ckZ3r0 I was thinking about structs actually. I have corrected the reasoning. The problem is that you cannot use one operator to define the other one because in one you are creating a new object while in the second you are mutating an existing object. With value types this would not be a problem. – Sulthan Feb 17 '19 at 22:27