Alecto
Alecto

Reputation: 10740

How do you write a protocol specifying the existence of an arithmetic operator in Swift?

Here's an example. Writing a function to multiply two doubles is pretty simple:

func MultiplyDoubles(_ x: Double, _ y: Double) {
    return x * y
}
MultiplyDoubles(3,5) // returns 15

But suppose I wanted to write a generic function to do this:

func MultiplyValues<T>(_ x: T, _ y: T) {
    return x * y //ERROR
}
MultiplyValues(3, 5)

But this throws an error: Binary operator '*' cannot be applied to to 'T' operands.

I understand that I'd need to write a protocol specifying that * can be applied to it, but how would I do this?

I tried doing:

protocol Multipliable {
    static func *(A:Multipliable, B: Multipliable) -> Multipliable
}
func MultiplyValues<T: Multipliable>(_ x: T, _ y: T) -> Multipliable {
    return x * y
}
MultiplyValues(3, 5)

Although this returns the message

error: MyPlayground.playground:15:19: error: argument type 'Int' does not conform to expected type 'Multipliable'
MultiplyValues(3, 5)
                  ^

Research: I've already looked at the documentation for protocols as well as the documentation for generics and for operators. I'm not writing a generic protocol, but rather a normal protocol that's meant to specify that it can be multiplied. This documentation explained how to overload operators, as well as how to create generic functions, and use protocols with generic functions, but none of them explained how to write a protocol specifying that an operator could be applied to the protocol.

Upvotes: 3

Views: 85

Answers (2)

Rob
Rob

Reputation: 437532

You can use the existing Numeric protocol:

func multiply<T: Numeric>(_ x: T, _ y: T) -> T {
    return x * y
}

But, let's imagine that such a protocol didn't exist. You can define your own and the specify which types conform to this protocol:

protocol Multipliable {
    static func *(lhs: Self, rhs: Self) -> Self
}

// These types already implement the above method, so all you need to do
// is declare conformance to your protocol with an empty extension.

extension Int: Multipliable { }
extension Double: Multipliable { }

// repeat for other types as you see fit

And then you can do:

func multiply<T: Multipliable>(_ x: T, _ y: T) -> T {
    return x * y
}

Upvotes: 4

OOPer
OOPer

Reputation: 47886

You can write something like this.

protocol Multipliable {
    static func *(A:Self, B: Self) -> Self
}
extension Int : Multipliable {}
//You need other extensions for other numeric types...

func MultiplyValues<T: Multipliable>(_ x: T, _ y: T) -> T {
    return x * y
}

MultiplyValues(3, 5)

But current Swift has some numeric protocols and you should better utilize them (as in Rob's answer).

Upvotes: 1

Related Questions