我创建了这个 中缀运算符 ^^
作为使用 pow
函数的替代:
infix operator ^^ { associativity left precedence 155 }
func ^^ <T: IntegerLiteralConvertible>(left: T, right: T) -> T {
return pow(left as Double, right as Double)
}
我使用IntegerLiteralConvertible
协议(protocol)作为泛型left
和right
的类型约束,因为根据我的理解this diagramm表明,它基本上包括所有数字类型。
为了使用 pow
函数,我必须将 left
和 right
向下转换为 Double
,我确实使用了 as
运算符。这不是最安全的方法,但这不是重点。
实现函数this way时 swift 告诉我:
<stdin>:4:12: error: cannot invoke 'pow' with an argument list of type '(Double, Double)'
return pow(left as Double, right as Double)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
据我所知,pow
需要两个 Double
作为参数,那么它为什么会提示这个呢?
最佳答案
why is it complaining about this?
因为 pow 返回 Double
.和 Double
不等于 T
.该错误消息具有误导性,但它的意思是“无法找到接受 pow
并返回 (Double, Double)
类型的 T
”
我认为您误解了 Swift 中的“cast”。在 Swift 中 as
不转换数值类型。
let intVal:Int = 12
let doubleVal:Double = intVal as Double
// ^ [!] error: 'Int' is not convertible to 'Double'
如果操作数的类型在编译时不可预测,则无效转换会导致运行时错误:
func foo<T: IntegerLiteralConvertible>(x: T) {
x as Double // <-- Execution was interrupted
}
foo(12 as Int)
相反,我们必须明确地“转换”它们。请参阅文档:Numeric Type Conversion
let intVal:Int = 12
let doubleVal:Double = Double(intVal)
之所以有效,是因为 Double
有init(_ v: Int)
初始值设定项。以下代码无法编译:
func foo<T: IntegerLiteralConvertible>(x: T) {
Double(x)
// ^~~~~~~~~ [!] error: cannot invoke 'init' with an argument of type 'T'
}
因为 Double
没有 init<T:IntegerLiteralConvertible>(_ val:T)
初始化程序。
所以,如果你想使用 pow()
, 你必须转换 T
至 Double
对于参数,并转换 Double
至 T
用于返回值。对此没有简单的解决方案。
关于Swift 的 pow() 函数不接受 Doubles 作为参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28702782/