@swift-4.2.4
protocol Equattable { func equaals(to other: Self) -> Bool } extension Int: Equattable { func equaals(to other: Int) -> Bool { return self == other } } extension String: Equattable { func equaals(to other: String) -> Bool { return self == other } } protocol _AnyEquattableBox { func _unbox<T: Equattable>() -> T? func _equaals(to box: _AnyEquattableBox) -> Bool? } struct _ConcreteEquattableBox<Base: Equattable> : _AnyEquattableBox { var _baseEquattable: Base init(_ base: Base) { self._baseEquattable = base } func _unbox<T: Equattable>() -> T? { return (self as _AnyEquattableBox as? _ConcreteEquattableBox<T>)?._baseEquattable } func _equaals(to box: _AnyEquattableBox) -> Bool? { guard let rhs: Base = box._unbox() else { return nil } return _baseEquattable.equaals(to: rhs) } } struct AnyEquattable: Equattable { var _box: _AnyEquattableBox init<E: Equattable>(_ base: E) { _box = _ConcreteEquattableBox(base) } func equaals(to rhs: AnyEquattable) -> Bool { return _box._equaals(to: rhs._box) ?? false } } let intVal1 = AnyEquattable(1) let intVal2 = AnyEquattable(1) let intVal3 = AnyEquattable(2) let strVal = AnyEquattable("test") assert(intVal1.equaals(to: intVal2)) assert(!intVal1.equaals(to: intVal3)) assert(!intVal1.equaals(to: strVal))