Generics 原始类型(Int、Float、Double)的泛型会创建奇怪的错误消息

Generics 原始类型(Int、Float、Double)的泛型会创建奇怪的错误消息,generics,swift,Generics,Swift,这里有人能看一下代码,告诉我有什么问题吗?我基本上尝试构建两个通用函数,它们在某些原始类型上运行,如Int、Float、Double等 不幸的是,我不能让它正常工作。这是起作用的代码(部分): 它返回30的正确结果。好的,到目前为止还不错。当我试图传递一个Ints数组时,事情变得很奇怪: extension Int : SummableMultipliable {} var intVec : [Int] = [1,2,3,4] vec_dot(intVec, intVec) 砰!在以下位

这里有人能看一下代码,告诉我有什么问题吗?我基本上尝试构建两个通用函数,它们在某些原始类型上运行,如
Int
Float
Double

不幸的是,我不能让它正常工作。这是起作用的代码(部分):

它返回
30的正确结果。好的,到目前为止还不错。当我试图传递一个
Int
s数组时,事情变得很奇怪:

 extension Int : SummableMultipliable {}
 var intVec : [Int] = [1,2,3,4]
 vec_dot(intVec, intVec)
砰!在以下位置引发异常:

 let x = (a[1] * b[1]) as Double
*thread#1:tid=0x139dd0,0x00000001018527ad libswiftCore.dylib`swift\u dynamicCast+1229,queue='com.apple.main thread',stop reason=EXC\u断点(code=EXC\u I386\u BPT,subcode=0x0)
*帧0:0x00000001018527ad libswiftCore.dylib`swift\u dynamicCast+1229
帧#1:0x000000010d6c3a09$uu lldb_expr248`uu lldb_expr_248; 248.vec_点(a=0x00007fff5e5a9648处的Swift.Array,b=0x00007fff5e5a9640处的Swift.Array)->操场248处的Swift.Double+921。Swift:54
帧#2:0x000000010d6c15b0$u lldb_expr248 `游戏场顶级代码+1456 248。swift:64
帧#3:0x000000010d6c4561$uu lldb_expr248`main+49 at:0
帧#4:0x000000010165b390 FirstTestPlayed`get_field_types_uuuuxCPappdelegate+160
帧#5:0x000000010165bea1 FirstTestPlayed `从@callee_owned()->(@unowned())到@callee_owned(@in())->(@out())+17的重分离thunk helper
帧#6:0x000000010165ab61 FirstTestPlayed `部分应用转发器重新提取从@callee_owned()->(@unowned())到@callee_owned(@in())->(@out())+81的thunk helper
帧#7:0x000000010165bed0 FirstTestPlayed `从@callee_owned(@in())->(@out())到@callee_owned()->(@unowned())+32的重新提取thunk helper
帧#8:0x000000010165bf07 FirstTestPlayed `从@callee_owned()->(@unowned())到@callee_unowned@objc_block()->(@unowned())+39的重分离thunk helper
帧#9:0x0000000101FEDAC CoreFoundation`\uuuu CFRUNLOOP\u正在调用\u OUT\u到\u块\uuu+12
帧#10:0x0000000101fe37f5 CoreFoundation`\uU CFRunLoopDoBlocks+341
帧#11:0x0000000101fe2fb3 CoreFoundation`\uu CFRunLoopRun+851
帧#12:0x0000000101fe29f6 CoreFoundation`CFRunLoopRunSpecific+470
帧#13:0x000000010208f2b1 CoreFoundation`CFRunLoopRun+97
帧#14:0x0000000101658be8 FirstTestPlayed`顶层代码+3784
帧#15:0x000000010165b3ba第一测试场`主+42
帧#16:0x0000000103cd9145 libdyld.dylib`start+1
我尝试了不同的角色:

let x = Double(a[i] * b[1])
错误:找不到接受提供的参数的“init”的重载

错误:无法使用类型为“T”的参数调用“init”

接下来,我尝试:

let y = Double(a[i]) * Double(b[1])
let x = y
错误:无法使用类型为“(Double,Double”)的参数列表调用“*”

我尝试了更多的东西。只要我尝试将
Int
作为泛型类型传递,就什么都不起作用了


也许我只是缺少了一些基本的东西,或者我太笨了,不懂泛型编程。在C++中,我将在2秒内完成。

< p>当用<代码> int 数组调用时,<代码> A[i] *b[i] < /C> >是<代码> int <代码>,不能被强制转换 使用
as
加倍

为了解决这个问题,您可以更改
vec_dot
函数以返回
T
对象,而不是一个
Double
。 要使初始化
var s:T=0
工作,必须使
summablemplicatable
源自
IntegerLiteralConvertible
(已符合
Int
Double
的要求):


或者,如果向量积始终应产生一个
双精度
,则可以 将
doubleValue()
方法添加到
summableMultipulable
协议:

protocol SummableMultipliable: Equatable {
    func +(lhs: Self, rhs: Self) -> Self
    func *(lhs: Self, rhs: Self) -> Self
    func doubleValue() -> Double
}

extension Double: SummableMultipliable {
    func doubleValue() -> Double { return self }
}

extension Int : SummableMultipliable {
    func doubleValue() -> Double { return Double(self) }
}

func vec_dot<T where T: SummableMultipliable>(a : [T], b: [T]) -> Double {
    assert(a.count == b.count, "vectors must be of same length")
    var s : Double = 0
    for var i = 0; i < a.count; ++i {
        let x = (a[i] * b[i]).doubleValue()
        s = s + x
    }
    return s
}

正如您可能已经注意到的那样,例外的原因是悲观情绪。公平地说,您试图做的是非法的,编译器一开始就不应该允许您这么做

由于
vec_dot
只知道
T
summablemployable
,它不能像那样将其转换为
Double
(它如何知道它不是
字符串?)

解决此问题的简单方法是,摆脱通用约束,改用函数重载:

func vec_dot(a: [Double], b: [Double]) -> Double {
    assert(a.count == b.count, "vectors must be of same length")
    var s: Double = 0.0
    for i in 0 ..< a.count {
        let x = (a[i] * b[i])
        s += x
    }
    return s
}

func vec_dot(a: [Int], b: [Int]) -> Double {
    return vec_dot(a.map({ Double($0) }), b.map({ Double($0) }))
}

var doubleVec: [Double] = [1, 2, 3, 4]
vec_dot(doubleVec, doubleVec) // 30.0

var intVec: [Int] = [1, 2, 3, 4]
vec_dot(intVec, intVec) // 30.0
func向量点(a:[Double],b:[Double])->Double{
断言(a.count==b.count,“向量必须具有相同的长度”)
变量s:Double=0.0
对于0中的i..Double{
返回向量点(a.map({Double($0)}),b.map({Double($0)}))
}
var doubleVec:[Double]=[1,2,3,4]
vec_点(doubleVec,doubleVec)//30.0
var intVec:[Int]=[1,2,3,4]
vec_点(intVec,intVec)//30.0


如果您仍然想坚持使用协议和泛型,请参阅。

作为一个小补充,我还建议使用
for I in 0..
而不是类似c的语法。回答得好。谢谢。我喜欢最后一个有拉链的。不知道Swift是如此受函数式编程的启发。小注:你的
vec_点(intVec,intVec)
返回一个双精度(30.0),而不是一个Int,正如注释所暗示的那样。
let y = Double(a[i]) * Double(b[1])
let x = y
protocol SummableMultipliable: Equatable, IntegerLiteralConvertible {
    func +(lhs: Self, rhs: Self) -> Self
    func *(lhs: Self, rhs: Self) -> Self
}

func vec_dot<T where T: SummableMultipliable>(a : [T], b: [T]) -> T {
    assert(a.count == b.count, "vectors must be of same length")
    var s : T = 0
    for var i = 0; i < a.count; ++i {
        let x = (a[i] * b[i])
        s = s + x
    }
    return s
}
var doubleVec : [Double] = [1,2,3,4]
let x = vec_dot(doubleVec, doubleVec)
println(x) // 30.0 (Double)
var intVec : [Int] = [1,2,3,4]
let y = vec_dot(intVec, intVec)
println(y) // 30 (Int)
protocol SummableMultipliable: Equatable {
    func +(lhs: Self, rhs: Self) -> Self
    func *(lhs: Self, rhs: Self) -> Self
    func doubleValue() -> Double
}

extension Double: SummableMultipliable {
    func doubleValue() -> Double { return self }
}

extension Int : SummableMultipliable {
    func doubleValue() -> Double { return Double(self) }
}

func vec_dot<T where T: SummableMultipliable>(a : [T], b: [T]) -> Double {
    assert(a.count == b.count, "vectors must be of same length")
    var s : Double = 0
    for var i = 0; i < a.count; ++i {
        let x = (a[i] * b[i]).doubleValue()
        s = s + x
    }
    return s
}
for i in 0 ..< a.count { ... }
let s : T = reduce(Zip2(a, b), 0) { $0 + $1.0 * $1.1 }
func vec_dot(a: [Double], b: [Double]) -> Double {
    assert(a.count == b.count, "vectors must be of same length")
    var s: Double = 0.0
    for i in 0 ..< a.count {
        let x = (a[i] * b[i])
        s += x
    }
    return s
}

func vec_dot(a: [Int], b: [Int]) -> Double {
    return vec_dot(a.map({ Double($0) }), b.map({ Double($0) }))
}

var doubleVec: [Double] = [1, 2, 3, 4]
vec_dot(doubleVec, doubleVec) // 30.0

var intVec: [Int] = [1, 2, 3, 4]
vec_dot(intVec, intVec) // 30.0