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?
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.