1

I have the following code:

protocol MyEnum {

}

class MyClass {
    func append(_ value: UInt8) {
        print("uint8 \(value)")
    }

    func append(_ value: UInt16) {
        print("uint16 \(value)")
    }

    func append<T: MyEnum>(_ value: T) {
        print("myenum \(value)")
    }
}

let c = MyClass()

func appendAny<T>(_ value: T) {
    switch value {
    case let u8 as UInt8:
        c.append(u8)
    case let u16 as UInt16:
        c.append(u16)
    case let myenum as MyEnum:
        c.append(myenum)
    default:
        assert(false)
    }
}

The error is reported by the compiler for the line c.append(myenum) stating

Cannot invoke 'append' with an argument list of type (MyEnum)

Please, explain to me why this happens and what is the correct solution in this case. I want to preserve my overloads, since when called with a concrete MyEnum instance, all works fine.

Aleks N.
  • 6,051
  • 3
  • 42
  • 42
  • 2
    This is another variant of http://stackoverflow.com/questions/33112559/protocol-doesnt-conform-to-itself: A protocol does not conform to itself. Change the third variant to `func append(_ value: MyEnum)` to make it compile. – Martin R Dec 05 '16 at 19:37
  • Thank you @MartinR that worked. I guess I've overengineered that generic ```append``` method a little bit. – Aleks N. Dec 05 '16 at 20:02

1 Answers1

1

As Martin noted in his comment, you should change your final append() overload to be:

func append(_ value: MyEnum) {
    print("myenum \(value)")
}

Because you want to treat the value as "an instance of a protocol", not an "instance of a concrete type that happens to conform to the protocol". An instance that has a protocol type is not also a concrete type that conforms to that protocol.

Another note: since you aren't really using generic constraints or any compile-time properties of the type T (only runtime casting), why not just change appendAny to be:

func appendAny(_ value: Any) {
    switch value {
    case let u8 as UInt8:
        c.append(u8)
    case let u16 as UInt16:
        c.append(u16)
    case let myenum as MyEnum:
        c.append(myenum)
    default:
        assert(false)
    }
}
Daniel Hall
  • 13,457
  • 4
  • 41
  • 37