首页 > 解决方案 > Type 'Any' does not conform to protocol 'Equatable' when trying to conform to an equatable generic Set

问题描述

I'm trying to create a base struct that supports a set of types (Int, Float, maybe string, possibly sometimes Vec4 matrix). I've built a base struct and conformed it to Hashable, made the type Equatable, but now I need to use this new struct in a Set.

This line:

struct AdjustmentSet: Set<BaseAdjustment<Any>>

where I declare the struct for the Set, is throwing

Type 'Any' does not conform to protocol 'Equatable'

Which of course is obvious in and of itself, but I don't know how to actually define a type here that works (I tried T: Equatable, Equatable, and nothing works).

struct BaseAdjustment<T: Equatable>: Hashable {

    var hashValue: Int {
        return displayName.hashValue
    }

    static func == (lhs: BaseAdjustment<T>, rhs: BaseAdjustment<T>) -> Bool {
        return lhs.displayName == rhs.displayName &&
            lhs.value == rhs.value &&
            lhs.isApplied == rhs.isApplied
    }

    var min: T?
    var max: T?
    var displayName: String = ""
    var value: T?
    var defaultValue: T?
    var isApplied: Bool = true

    init(min: T, max: T, displayName: String, defaultValue: T?) {
        self.min = min
        self.max = max
        self.displayName = displayName
        self.defaultValue = defaultValue
        self.value = defaultValue
        self.isApplied = true
    }
}

struct AdjustmentSet: Set<BaseAdjustment<Any>> {
    static var brightness   = BaseAdjustment<CGFloat>(min: 0, max: 1, displayName: "Brightness", defaultValue: 0)
    static var exposure     = BaseAdjustment<CGFloat>(min: 0, max: 1, displayName: "Exposure", defaultValue: 0)
    static var contrast     = BaseAdjustment<CGFloat>(min: 0, max: 1, displayName: "Contrast", defaultValue: 0)
}

Addendum:

I'm hopeful that with the introduction of Opaque Types in Swift 5, we can do away with this complexity by defining the set of type some BaseAdjustment.

标签: iosswiftgenericsset

解决方案


AdjustmentSet has to itself be generic:

struct AdjustmentSet<T: Equatable>: Set<BaseAdjustment<T>> {

}

But then of course, Set is a struct, not a class or protocol, so it can't be subtyped like this.


推荐阅读