Avatar
@swift-4.2.4 protocol AnyEquatableBox { func _unbox<T: Equatable>() -> T? func _equals(to box: AnyEquatableBox) -> Bool? } struct ConcreteEquatableBox<Base: Equatable>: AnyEquatableBox { var base: Base init(_ base: Base) { self.base = base } func _unbox<T: Equatable>() -> T? { return self.base as? T } func _equals(to box: AnyEquatableBox) -> Bool? { guard let rhs: Base = box._unbox() else { return nil } return base == rhs } } struct AnyEquatable: Equatable { var box: AnyEquatableBox init<E>(_ base: E) where E: Equatable { box = ConcreteEquatableBox(base) } static func == (lhs: AnyEquatable, rhs: AnyEquatable) -> Bool { return lhs.box._equals(to: rhs.box) ?? false } } class Animal: Equatable { static func == (lhs: Animal, rhs: Animal) -> Bool { return lhs === rhs } } class Cat : Animal {} class Dog : Animal {} let a = Cat() let b: Animal = a let c: Animal = Dog() assert(AnyEquatable(a) == AnyEquatable(b)) assert(AnyEquatable(a) != AnyEquatable(c)) assert(AnyEquatable(b) == AnyEquatable(a)) assert(AnyEquatable(b) != AnyEquatable(c)) assert(AnyEquatable(c) != AnyEquatable(a)) assert(AnyEquatable(c) != AnyEquatable(b))