[swift-users] Type "T?" does not conform to protocol 'Equatable'

Rudolf Adamkovič salutis at me.com
Mon Feb 29 12:24:44 CST 2016


Wow! Thanks for (extra-extra-extra) detailed answer. I will try this.

R+

> On 29 Feb 2016, at 17:41, davesweeris at mac.com wrote:
> 
> To the best of my understanding, Int? is not equatable. Your let c = a == b  code works because this function (or something like it) is defined:
> func == <T: Equatable> (lhs: Optional<T>, rhs: Optional<T>) -> Bool {
>     switch (lhs, rhs) {
>     case (.None, .None): return true
>     case (.Some(let l), .Some(let r)): return l == r
>     default: return false
>     }
> }
> 
> The reason it’s done this way is that currently there’s no mechanism for conditional protocol conformance. Ideally, you’d be able to write something like this:
> extension Optional : Equatable where T: Equatable {}
> … which, combined with that existing == function, would make Int? be equatable.
> 
> IIRC, Apple is intending to remove this limitation, but I can’t remember if it’s made the cut for Swift 3 or if it’ll be later on.
> 
> In the meantime, if Keith’s solution of making the variable be a T? instead of T doesn’t work for you, I think this will let you continue on with other parts of your code (although I have NOT thoroughly tested it… use at your own risk):
> public struct OptionalWrapper<T> : Equatable {
>     typealias Wrapped = T
>     var unwrap: Wrapped?
>     init(_ value: Wrapped?) { unwrap = value }
> }
> public func == <T: Equatable> (lhs: OptionalWrapper<T>, rhs: OptionalWrapper<T>) -> Bool {
>     switch (lhs.unwrap, rhs.unwrap) {
>     case (.None, .None): return true
>     case (.Some(let l), .Some(let r)): return l == r
>     default: return false
>     }
> }
> public func == <T: Equatable> (lhs: OptionalWrapper<T?>, rhs: OptionalWrapper<T?>) -> Bool {
>     switch (lhs.unwrap, rhs.unwrap) {
>     case (.None, .None): return true
>     case (.Some(let l), .Some(let r)): return l == r
>     default: return false
>     }
> }
> public func == <T> (lhs: OptionalWrapper<T>, rhs: OptionalWrapper<T>) -> Bool {
>     switch (lhs.unwrap, rhs.unwrap) {
>     case (.None, .None): return true
>     case (.Some, .None): return false
>     case (.None, .Some): return false
>     case (.Some, .Some): fatalError("\(__FILE__):\(__LINE__):\(__COLUMN__): Binary operator '==' cannot be applied to two '\(T.self)' operands")
>     }
> }
> 
> The syntax for actually using it is a bit long, but it should work: 
> let a = C(t: OptionalWrapper(4)) // infers that Wrapped == Int
> let b = C(t: OptionalWrapper<Int>(nil)) // must be explicit since nil is just Optional.None, without any other type info
> let c = a.t == b.t // false
> 
> Hope that helps
> 
> - Dave Sweeris
> 
>> On Feb 29, 2016, at 8:24 AM, Rudolf Adamkovič via swift-users <swift-users at swift.org <mailto:swift-users at swift.org>> wrote:
>> 
>> Hi everyone!
>> 
>> I have a generic class similar to this one:
>> 
>> class C<T: Equatable> {
>>     let t: T
>>     init(t: T) { self.t = t }
>> }
>> 
>> When try to wrap ‘Int?' inside, I get the following error:
>> 
>> let a = C<Int?>(t: nil) // ERROR: Type "Int?" does not conform to protocol 'Equatable'
>> 
>> Yet when I try to compare two ‘Int?’ values, everything works:
>> 
>> let a: Int? = 5
>> let b: Int? = 6
>> 
>> let c = a == b // NO ERROR
>> 
>> So, is ‘Int?' equatable or not?
>> 
>> Thanks!
>> 
>> R+
>> _______________________________________________
>> swift-users mailing list
>> swift-users at swift.org <mailto:swift-users at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-users
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160229/326d559f/attachment.html>


More information about the swift-users mailing list