Oliver Borchert Oliver Borchert - 10 months ago 42
Swift Question

Swift generic constraints based on operator

Suppose I want to add up all the values of an entry of an array. Not only integers, but also double values or some type I created myself which implements the + operator. So my question is: Is it possible to create such a function with a constraint that is based on the fact if the type implements the operator? Such as or something like that (obviously THIS isn't working).

Thanks in advance


There are several ways you can approach the problem.


While I know of no explicit way to say "Hey Swift, I want to only allow type T where T has this operator", all types we commonly think of as capable of being added, subtracted, multiplied, and divided automatically conform to IntegerArithmeticType, which can be used as a generic constraint for any generic function or type.

For example:

func addAll<T: IntegerArithmeticType>(array: [T]) -> T {
    var count = array[0]
    for (index, value) in array.enumerate() {
        if index != 0 {
            count += value
    return count

Notice in this quick mock-up version I initialized count with the first value of the array and then avoiding double-counting by checking the index against 0 inside the for loop. I can't initialize count with 0 because 0 is an Int while I want count to be of type T.

You mentioned having your own types work with this too. One option is to have your custom type conform to IntegerArithmeticType, although it requires a lot more than just the + operator. For details on IntegerArithmeticType, see SwiftDoc.

Custom Protocol

If conforming to IntegerArithmeticType imposes some sort of limitation on you, you can create a custom protocol with the + function and whatever other requirements you would like. After all, operators are really just functions. Note that you can add conformance to already existing types with extensions. For example:

protocol Addable {
    func +(left: Self, right: Self) -> Self
    // Other requirements...

extension Int: Addable {}
extension Double: Addable {}