How do I check if a type / instance conforms to a protocol that "has Self or associated type requirements"?

Int types conform to the BinaryInteger protocol. But how do I check the conformance?

Doing this:

0 is BinaryInteger

gives me an error:

error: protocol 'BinaryInteger' can only be used as a generic constraint because it has Self or associated type requirements

1 Like

You could try an indirect approach based on function overloading:

enum Conformance {
  case BinaryInteger, Collection
}

func conformance<T: Collection>(of instance: T) -> Conformance { .Collection }
func conformance<T: BinaryInteger>(of instance: T) -> Conformance { .BinaryInteger }

conformance(of: 3)          // returns Conformance.BinaryInteger
conformance(of: [1, 2, 3])  // returns Conformance.Collection

Your example becomes:

if conformance(of: 0) == .BinaryInteger { ... }
7 Likes

If you literally just want to know if something conforms to such a protocol, and you don’t need to actually use the conformance for anything, you can check like this:

protocol ConformanceMarker {}
enum BinaryIntegerMarker<T> {}
extension BinaryIntegerMarker: ConformanceMarker where T: BinaryInteger {}

func isBinaryIntegerType<T>(_ t: T.Type) -> Bool {
  return BinaryIntegerMarker<T>.self is ConformanceMarker.Type
}

func isBinaryInteger<T>(_ t: T) -> Bool {
  return isBinaryIntegerType(T.self)
}

If you actually want to use the conformance for something, it gets more tricky. See this thread for details.

Original strategy by Matt Johnson here (explanatory description by myself here)

Modular solution with better encapsulation properties by myself here (and the next comment after it)

Simple quick-and-dirty approach by Dave Abrahams here

5 Likes