Swift's pow() function won't accept Doubles as arguments
downcast, generics, pow, swift, type-constraints
Solution
why is it complaining about this?
Because pow returns `Double`. And `Double` is not identical to `T`. The error message is misleading, but it means "Cannot find `pow` that accepts `(Double, Double)` and returns `T` type"
I think you are misunderstanding "cast" in Swift. In Swift `as` does not convert numeric types.
let intVal:Int = 12
let doubleVal:Double = intVal as Double
// ^ [!] error: 'Int' is not convertible to 'Double'
And If the type of operand is not predictable at compile time, invalid casting causes runtime error:
func foo<T: IntegerLiteralConvertible>(x: T) {
x as Double // <-- Execution was interrupted
}
foo(12 as Int)
Instead, we must explicitly "convert" them. see the document: Numeric Type Conversion
let intVal:Int = 12
let doubleVal:Double = Double(intVal)
This works only because `Double` has `init(_ v: Int)` initializer. The following code does not compile:
func foo<T: IntegerLiteralConvertible>(x: T) {
Double(x)
// ^~~~~~~~~ [!] error: cannot invoke 'init' with an argument of type 'T'
}
Because `Double` does not have `init<T:IntegerLiteralConvertible>(_ val:T)` initializer.
So, if you want to use `pow()`, you must convert `T` to `Double` for arguments, and convert `Double` to `T` for returning value. And there is no simple solution for that.
Problem
I created this `infix operator ^^` as a substitute to using the `pow` function: ``` infix operator ^^ { associativity left precedence 155 } func ^^ <T: IntegerLiteralConvertible>(left: T, right: T) -> T { return pow(left as Double, right as Double) } ``` I used the `IntegerLiteralConvertible` protocol as a type constraint for the generics `left` and `right`, because from my understanding this diagramm shows, that it basically includes all number types. In order to use the `pow` function I have to downcast `left` and `right` to `Double` though, which I did using the `as` operator. It's not the safest approach, but that's besides the point. When implementing the function this way swift tells me: ``` <stdin>:4:12: error: cannot invoke 'pow' with an argument list of type '(Double, Double)' return pow(left as Double, right as Double) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` Now as far as I know `pow` takes two `Double`s as parameters, so why is it complaining about this?