In Swift, how to generally restrict a function to types that understand T + T

I would like to have a generic function that can use the plus operator for 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 return x + y

I’m the only option to follow the sentence in this answer: https://stackoverflow.com/a/2126262/2128 and create your own protocol as Int and String will define the operator

+7
generics swift
source share
2 answers

You must do what this answer suggested. Create a protocol to use and extend all the classes you want to use. Then make sure that T implements this protocol in your method signature.

You cannot use the incremental protocol because it is not in the fast protocol. The fast library actually creates a + function for each valid add operation. Command-click on something like Int to see where they are all defined. It will look something like this:

 //.... func +(lhs: Int8, rhs: Int8) -> Int8 func +(lhs: UInt16, rhs: UInt16) -> UInt16 func +(lhs: Int16, rhs: Int16) -> Int16 func +(lhs: UInt32, rhs: UInt32) -> UInt32 func +(lhs: Int32, rhs: Int32) -> Int32 //etc... 
+5
source share

You may have a similar need for other functions, and their implementation for all types with integer and floating point (or other "summed" things) will lead to massive duplication of code.

One partial solution, specifically for +, -, *, /,%, should require IntegerArithmeticType protocol compliance:

 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 the overflow operations defined in the _IntegerArithmeticType protocol, which inherits IntegerArithmeticType.

However, type extensions for the specific consistent functionality of the operator function are not "annoying" as you 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 you can use Summable in your code forever:

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

In fact, and as @connor pointed out, this is equivalent to what you mentioned in response to @ Jean-PhilippePellet.

+10
source share

All Articles