Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Swift, how to generically limit function to types that understand T + T

Tags:

generics

swift

I would like to have a generic function that can use the plus operator on two values.

class funccalc {
    func doAdd<T>(x:T,y:T) -> T {
        return x + y
    }
}
let a = funccalc()
println(a.doAdd(1, y: 4))
println(a.doAdd(23.54, y:200))

I get an error on return x + y

Is my only option to follow the suggestion in this answer: https://stackoverflow.com/a/24047239/67566, and create my own protocol as Int and String would define the operator?

like image 720
James Black Avatar asked Jun 12 '14 00:06

James Black


2 Answers

Have you tried using the protocol AdditiveArithmetic?

https://developer.apple.com/documentation/swift/additivearithmetic

Looks like thats exactly what you are looking for. That protocol has the method:

static func + (Self, Self) -> Self

Using that protocol your method becomes:

class funccalc {
    func doAdd<T: AdditiveArithmetic>(x:T,y:T) -> T {
        return x + y
    }
}
like image 67
J.beenie Avatar answered Oct 03 '22 08:10

J.beenie


You may have a similar need for other functions too and implementing them for all integer and floating point types (or other "summable" things) would cause massive code duplication.

One partial solution, specifically for +, -, *, /, % is to require conformance to IntegerArithmeticType protocol:

func example<T: IntegerArithmeticType>(x: T, y: T) -> T { return x + y }
println(example(40, 2)) // --> 42

This does not apply to floating point types because they do not implement overflow operations defined in _IntegerArithmeticType protocol, which IntegerArithmeticType inherits from.

However, extending types for a specific globally defined operator function conformance is not as "annoying" as you might think:

protocol Summable { func +(lhs: Self, rhs: Self) -> Self }

extension Int: Summable {}
extension Double: Summable {}
extension String: Summable {}
// extension for any other types... you are in full control!

You do this once, then forevermore you can use Summable in you code:

func example<T: Summable>(x: T, y: T) -> T { return x + y }

println( example("4", "2") ) // --> 42

Indeed, and as @connor pointed out, this is equivalent to @Jean-PhilippePellet's answer you mentioned.

like image 29
Milos Avatar answered Oct 03 '22 09:10

Milos