gpt4 book ai didi

xcode - swift 泛型 : More specialized than generic?

转载 作者:可可西里 更新时间:2023-11-01 00:24:30 26 4
gpt4 key购买 nike

XCode 6:测试版 5:

目标:

我正在尝试为语义兼容但不共享(或似乎共享)足够的协议(protocol)的类型编写泛型代码,以使我的泛型基于共享协议(protocol)的子集。到目前为止,我还没有找到解决方案,我想知道我是否遗漏了一些东西,或者它是否是语言的限制 - 任何见解都将受到赞赏。

问题:

我有一些函数只在类型上有所不同,在语义上没有区别,看起来很适合泛型。我遇到的问题是,据我所知,Swift 执行的似乎是泛型的解析时绑定(bind),如果可能存在问题则失败,而不是在实际存在问题时失败。

示例:

在人为的示例中考虑以下通用函数:

func defVal<T where T:FloatingPointType, T:FloatLiteralConvertible>(T.Type) -> T {
return 0.0
}

func defVal<T:IntegerLiteralConvertible>(T.Type) -> T {
return 0
}

请注意,我提供的函数应该跨越整数和 float 的情况,并且有意不想提供与我无关的所有可能变体的详尽列表。

然后我想定义跨类型的通用代码——在这个例子中,是 int 和 float 类型。请注意,即使没有任何调用它的代码,此代码也无法编译:

func doSomethingGeneric<T>(t:T) -> [T]
{
let a = defVal(T) // Type 'T' does not conform to protocol FloatLiteralConvertible
let b = a * a // works
return [t]
}

在我的内存中,这会在 C++ 中编译,直到您使用不兼容的类型调用它,此时编译器会捕获它。

我还尝试了其他效用降低的变体:

func doSomethingWithFloats<T
where T:FloatingPointType, T:FloatLiteralConvertible>(t:T) -> [T]
{
let a = defVal(T) // works
let b = a * a // T is not convertible to UInt8
// - need a floating point arithmetic type?

let c = -a // T is not convertible to Float
let f:Float = -a // T is not convertible to Float
return [t]
}

鉴于 Swift 提供协议(protocol)作为对具体实例(专用的,而非通用的)进行分组的一种方式,我编写了一个协议(protocol)集:

protocol Initializable {}
extension Float : Initializable {}
extension Double : Initializable {}
extension CGFloat : Initializable {}

func doSomethingWithInitializable<T:Initializable>(t:T) -> [T]
{
let a = defVal(T) // Type 'T' does not conform to protocol FloatLiteralConvertible
let b = a * a // works
return [t]
}

请注意,即使在所有 Initializable 类型的集合中实现了 FloatLiteralConvertible,这也会失败。换句话说,Swift 似乎过早地绑定(bind)了泛型类型,并且将泛型类型视为专门化的具体实例,而不是一个更大的模式,可以在链的更下方进行编译。此外,请注意,虽然我可以从 FloatLiteralConvertible 派生,但这会使我无法支持 int 类型等。如果有一个通用的 ArithmeticType 协议(protocol),可以想象它可以工作,但我没有看到任何类似的东西。这就是问题的症结所在 - 没有适用于两者的通用协议(protocol),即使 int 和 floating 类型在语义上是兼容的(具有相同的数学规则)。

总而言之,如何编写类型在语义上兼容但没有足够的跨越协议(protocol)来按协议(protocol)过滤的泛型函数(在这种情况下 - FloatingPointType 不实现 IntegerArithmeticType,但在语义上能够算术)。

提前致谢。

最佳答案

与 C++ 不同,Swift 不会通过在调用站点替换具体类型并制作非泛型副本来处理泛型(至少在一般情况下它不会 - 作为允许的优化,但我离题了)

Swift 通过在每次调用时将描述实际类型的元数据信息传递给一个主函数来处理通用性,然后主函数使用元数据提供的入口点来操作您的对象

在您的示例中,Initializable 不提供任何操作,因此当编译器尝试执行 defVal(T) 时,它不知道该做什么(它如何确保您的类型有 defVal 重载?)

你要做的实际上是在 Initializable 协议(protocol)上将 defVal 定义为静态函数,然后在扩展中实现它,然后 Swift 就会知道 T.defVal() 意味着类似于

metadata[Initializable]->defVal(metadata)

哦,因为你正在尝试执行 *(T,T),你可能还想制作一个可乘协议(protocol),然后你的 T 将被键入为

<T: protocol<Initializable,Multipliable>>

关于xcode - swift 泛型 : More specialized than generic?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25275032/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com