Xcode Swift仿制药:比仿制药更专业?

Xcode Swift仿制药:比仿制药更专业?,xcode,generics,swift,Xcode,Generics,Swift,代码6:Beta 5: 目标: 我试图为语义兼容但不共享(或似乎共享)足够的协议的类型编写泛型代码,以使我的泛型基于共享协议的子集。到目前为止,我还没有找到一个解决方案,我想知道我遗漏了什么,或者这是语言的一个局限性——任何洞察都是值得赞赏的 问题: 我有一些函数,它们只在类型上不同,在语义上不同,而且似乎很适合泛型。我遇到的问题是,据我所知,斯威夫特做的似乎是泛型的解析时间绑定,如果可能存在问题,就失败了,而不是当实际存在问题时 示例: 在一个精心设计的示例中考虑以下通用函数: func de

代码6:Beta 5:

目标:

我试图为语义兼容但不共享(或似乎共享)足够的协议的类型编写泛型代码,以使我的泛型基于共享协议的子集。到目前为止,我还没有找到一个解决方案,我想知道我遗漏了什么,或者这是语言的一个局限性——任何洞察都是值得赞赏的

问题:

我有一些函数,它们只在类型上不同,在语义上不同,而且似乎很适合泛型。我遇到的问题是,据我所知,斯威夫特做的似乎是泛型的解析时间绑定,如果可能存在问题,就失败了,而不是当实际存在问题时

示例:

在一个精心设计的示例中考虑以下通用函数:

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

func defVal<T:IntegerLiteralConvertible>(T.Type) -> T {
    return 0
}
函数定义(T.Type)->T{
返回0.0
}
函数定义(T.Type)->T{
返回0
}
请注意,我提供的函数应该跨越整数和浮点的情况,并且有意不想提供与我无关的所有可能变化的详尽列表

然后我想定义跨越类型的通用代码——在本例中是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]
}
func doSomethingGeneric(t:t)->[t]
{
设a=deffal(T)//类型“T”不符合协议floatLiteralConverable
让b=a*a//起作用
返回[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]
}
func doSomethingWithFloats(t:t)->[t]
{
设a=deffal(T)//工作
设b=a*a//T不能转换为UInt8
//-需要浮点算术类型吗?
设c=-a//T不能转换为浮点数
设f:Float=-a//T不能转换为Float
返回[t]
}
鉴于Swift提供协议作为对具体实例进行分组的一种方式(专门的,而非通用的),我制定了一个协议:

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]
}
协议可初始化{}
扩展浮点:可初始化{}
双扩展名:可初始化{}
扩展CGFloat:可初始化{}
func dosomething可初始化(t:t)->[t]
{
设a=deffal(T)//类型“T”不符合协议floatLiteralConverable
让b=a*a//起作用
返回[t]
}
请注意,即使在所有可初始化类型集中实现了FloatLiteralConvertible,这也会失败。换句话说,Swift似乎过早地绑定了泛型类型,并将泛型类型视为专门化的具体实例,而不是更大的模式,该模式将进一步编译。此外,请注意,虽然我可以从FloatLiteralConvertible派生,但这将阻止我支持int类型等。如果有一个通用的算术类型协议,这可能会起作用,但我看不到任何类似的情况。这就是问题的症结所在——尽管int和floating类型在语义上都是兼容的(具有相同的数学规则),但没有一个通用的协议同时适用于两者

总之,如何编写泛型函数,这些函数的类型在语义上是兼容的,但是没有足够的跨协议来按协议进行过滤(在本例中,FloatingPointType不实现IntegerArithmeticType,但在语义上能够进行算术)


谢谢。

< P> > C++不同,Swift不通过调用调用站点中的具体类型,而非泛型复制(一般来说它不作为优化,但我离题)

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

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

实际上,您要做的是在可初始化协议上将deffal定义为一个静态函数,然后在扩展中实现它,这样Swift就会知道T.deffal()的含义类似于

metadata[Initializable]->defVal(metadata)
哦,因为您正试图执行一个*(T,T),您可能还想创建一个可复用协议,然后您的T将被键入为

<T: protocol<Initializable,Multipliable>>


谢谢你,恩里科。这听起来像是在功能上有一个漏洞:Swift泛型看起来更像是“通过协议抽象”,而不是泛型——一般意义上的泛型。我不知道语义是否会影响模板膨胀,但语言解决方案是最好的,否则,就采用更正交的协议。查找通用协议的模块文件确实会降低生产效率,而且很容易对对本机类型进行太多更改感到缄默。再次感谢-C这种“实例化”似乎禁用了大多数编译器的优化机会。对拆卸的检查证实了这一怀疑。Enrico,如果你能“离题”一点,详细阐述这个问题,我将不胜感激,可能在其他地方;)您为什么要调用
deffal(T)
?您正在将类型传递给需要值的函数。你是说<代码> DEVALVE(T)< /C> >?@ Rekistor,我想要T+()的C++等价物,但不存在,所以我创建了一个函数,它采用了类型(t类型),而不是一个实例(t),并返回了该类型的默认值。我不想创建一个默认的初始值设定项,因为它太笼统,会影响其他地方的语义。我实际上是在试图解决另一个问题,那只是一种手段,一个sim卡