2

Say you have a protocol ToString that is implemented for Int, and a function that takes an array of ToStrings.

Trying to pass an array of Ints to this function results in the error Cannot convert value of type '[Int]' to expected argument type '[ToString]'.

However, using map on the array before passing it to the function works. Is this the supposed way to do the type cast or is there a way that doesn't result in iterating over the array? Or is this optimized out by the compiler?

Full example:

protocol ToString {
  func toString() -> String
}

extension Int: ToString {
  func toString() -> String {
    return "\(self)"
  }
}

func log( values: [ToString]) {
  values.forEach { print( $0.toString()) }
}

let values: [Int] = [1, 2, 3]

// Error: Cannot convert value of type '[Int]' to expected argument type '[ToString]'
log( values)

// No error
log( values.map { $0 })
lassej
  • 6,256
  • 6
  • 26
  • 34
  • 3
    The reason for the error "Cannot convert value of type '[Int]' to expected argument type '[ToString]'" is explained here: [Type conversion when using protocol in Swift](http://stackoverflow.com/questions/38387256/type-conversion-when-using-protocol-in-swift): Converting `[Int]` to `[ToString]` requires conversion of each element. – So this is partly a duplicate. But since you asked for alternative solutions (and one is given below) I decided to leave it open. – Martin R Aug 02 '16 at 05:36

1 Answers1

3

This Q&A explains the problem. I will suggest a fix that avoids creation of a new array: make your log function generic, and add a type constraint on its type parameter, requiring it to conform to ToString protocol:

func log<T:ToString>( values: [T]) {
    values.forEach { print( $0.toString()) }
}

Now Swift lets you call your function with arrays of any type, as long as array elements conform to ToString protocol.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Thanks for the link to the Q&A and the answer. It solves the problem from my question nicely, although the actual problem I have is that I want to cast an array from a sub-protocol to an array of a super-protocol and the actual types may not all be the same. But I think I'll add that issue to the linked Q&A. – lassej Aug 02 '16 at 07:38