尝试符合可等式泛型 Set 时,类型“任何”不符合协议“等式”

Posted

技术标签:

【中文标题】尝试符合可等式泛型 Set 时,类型“任何”不符合协议“等式”【英文标题】:Type 'Any' does not conform to protocol 'Equatable' when trying to conform to an equatable generic Set 【发布时间】:2019-02-22 02:30:25 【问题描述】:

我正在尝试创建一个支持一组类型(Int、Float、可能是字符串,有时可能是 Vec4 矩阵)的基本结构。我已经构建了一个基本结构并将其与 Hashable 保持一致,将类型设为 Equatable,但现在我需要在 Set 中使用这个新结构。

这一行:

struct AdjustmentSet: Set<BaseAdjustment<Any>>

我在哪里声明 Set 的结构,是在抛出

类型“Any”不符合协议“Equatable”

这当然是显而易见的,但我不知道如何在此处实际定义一个有效的类型(我尝试了T: EquatableEquatable,但没有任何效果)。

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)


附录:

我希望通过在 Swift 5 中引入 Opaque Types,我们可以通过定义 some BaseAdjustment 类型的集合来消除这种复杂性。

【问题讨论】:

【参考方案1】:

AdjustmentSet 本身必须是通用的:

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


当然,Set 是一个结构,而不是一个类或协议,所以它不能像这样子类型化。

【讨论】:

呸。那么如何使用集合(或类似集合的协议/结构)来解决这个问题?我基本上需要一组独特的 BaseAdjustment 实例。 @brandonscript 那么你所拥有的不是一个集合,它只是一系列静态变量。你到底想达到什么目的? 最终这组属性会显示在一个数组中,并且会在某些点被添加或删除。所以,基本上,就像一个集合。但是每个属性都需要特定的子属性,例如结构中的子属性。我可以写所有这些,而且我可能不得不这样做,但如果 Set 可以做到,我为什么要这样做? @brandonscript 听起来你需要包装一个集合,而不是子类化它。 愿意为我指明正确的方向吗?我在文档中找不到太多帮助,或者我没有找对地方。

以上是关于尝试符合可等式泛型 Set 时,类型“任何”不符合协议“等式”的主要内容,如果未能解决你的问题,请参考以下文章

类型“任何”不符合协议“序列”

泛型类型在不透明类型的帮助下符合序列:一些 IteratorProtocol

这个深奥的泛型错误是编译器错误还是新限制? (推断类型不符合上限)

符合 Swift 协议的泛型类型

字符串字典:任何不符合协议“可解码”[重复]

Swift:检查泛型类型是不是符合协议