1

我正在尝试对受泛型类型约束的泛型类进行扩展。这是我认为应该工作的代码的简化:

struct Thing<T> {
    var value: T
}

struct ContainsStringThing {
    var stringThing: Thing<String>
}

extension Thing where T == String {                           // <-- Error location
    func containedStringThing() -> ContainsStringThing {
        return ContainsStringThing(stringThing: value)
    }
}

但是,我收到以下错误消息:

相同类型的要求使泛型参数“T”非泛型

我搜索了解决此问题的方法,并找到了使用协议来约束扩展而不是类型的建议:链接到文章。这样做之后,我最终得到了这个:

protocol StringProtocol { }

struct Thing<T> {
    var value: T
}

struct ContainsStringThing {
    var stringThing: Thing<StringProtocol>
}

extension Thing where T: StringProtocol {
    func containedStringThing() -> ContainsStringThing {
        return ContainsStringThing(stringThing: self)         // <-- Error location
    }
}

现在它确实让我限制了扩展,但它显示了不同的错误消息:

无法将类型“Thing<T>”的值转换为预期的参数类型“Thing<StringProtocol>”

基本上现在它知道它本身T符合协议StringProtocol,但是在引用整个对象时它不知道它Thing<T>

是否有任何解决方法,或者我应该将其作为进化提案提交给 swift 邮件列表?

注意:所有代码都是在操场上测试的,你可以复制粘贴来试试。

4

1 回答 1

0

作为一种解决方法,您可以使用 self 的值创建一个新的 Thing 实例。

extension Thing where T: StringProtocol {
    func containedStringThing() -> ContainsStringThing {
        return ContainsStringThing(stringThing: Thing<StringProtocol>(value: self.value))
    }
}

在 Swift 2.2 中,这样的扩展约束意味着containsStringThing()函数将可用于值类型符合 StringProtocol 的 Thing 实例。

如果 Swift 编译器可以将self.value的类型推断为StringProtocol那就太好了。在这种情况下,您可以只写 ContainsStringThing(stringThing: self)而不是 ContainsStringThing(stringThing: Thing<StringProtocol>(value: self.value)). 你绝对应该填写一份提案。

于 2016-07-05T21:45:16.963 回答