Andrej Andrej - 1 year ago 70
Swift Question

Generic function for type that implements common interface

I'd like to increase my knowledge of generics and I come to a problem I can't solve. I have two different types (

). Both types implement a function
. I want to make a generic function to call
on a given type.

The benefit would be so that I could replace
with a single

Here's my playground:

let myDouble: Double = 1
let myInt: Int = 2

func intAdvanceByTen(value: Int) { // Replace this function
value.advanced(by: 10)

func doubleAdvanceByTen(value: Int) { // ...and this function
value.advanced(by: 10)

protocol CanAdvance {
func advance(_ by: Any)
// ...with this generic function
func genericAdvanceByTen(value: CanAdvance) {

genericAdvanceByTen(value: myInt) // Error: Argument "Int" does not conform to expected type "CanAdvance"

How to make the generic function know that the passed type implements the

Answer Source

Try this:

protocol CanAdvance {
    // This method is intentionally designed to have the same signature as the
    // methods built into Int and Double
    func advanced(by: Self) -> Self

    // We need this primarily for the definition of the constant 10. The built
    // in `advanced` function requires the distance to be of the same type.
    // The conversion syntax in Swift is via init:
    //      let aDouble = Double(anInt)
    // Not the C-like cast:
    //      let aDouble = anInt as! Double    // invalid
    // Hence we must have a way to convert 10 to the appropriate Int or Double.
    // Conveniently, both types can convert from an Int32 so we  put this
    // requirement in the protocol
    init(_ value: Int32)

extension Int : CanAdvance { }
extension Double : CanAdvance { }

func genericAdvanceByTen<T: CanAdvance>(value: T) -> T {
    let distance = T(10)
    return value.advanced(by: distance)

genericAdvanceByTen(value: 2)       // 12
genericAdvanceByTen(value: 3.14)    // 13.14
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download