Swift generics aren't like C++ templates.
In C++, you can just try to use a parameterized type however you want, and it's not an error until the compiler tries to instantiate the template with some type that doesn't support what your template tries to do.
In Swift, the generic construct can only use a parameterized type in ways known to be valid when the generic construct is first parsed. You specify these "ways known to be valid" by constraining the parameterized type with protocols.
You cannot call sqrt
or pow
with generic-typed arguments, because those functions are not themselves generic. They have each two definitions:
func pow(_: Double, _: Double) -> Double
func pow(lhs: Float, rhs: Float) -> Float
func sqrt(x: Double) -> Double
func sqrt(x: Float) -> Float
You could write type-specific versions of hypotenusa
:
func hypotenusa(a: Float, b: Float) -> Float
func hypotenusa(a: Double, b: Double) -> Double
func hypotenusa(a: CGFloat, b: CGFloat) -> CGFloat
I'm not sure why you'd create an Int
version at all, since very few right triangles have integer hypotenuses.
Anyway, you don't need to define the Float
and Double
versions at all, because the standard library already provides a hypot
function defined on Float
and Double
:
func hypot(_: Double, _: Double) -> Double
func hypot(lhs: Float, rhs: Float) -> Float
You could create another override for CGFloat
:
func hypot(l: CGFloat, r: CGFloat) -> CGFloat {
return hypot(Double(l), Double(r))
}
As for your addition
function, it has the same problem as your hypotenusa
function: the +
operator is not defined entirely generically. It has some generic definitions (unlike sqrt
and pow
), but those only cover the integer types (see IntegerArithmeticType
). There's not generic definition of +
that covers the floating-point types. Swift defines all of these versions of +
with explicit types:
func +(lhs: Float, rhs: Float) -> Float
func +<T>(lhs: Int, rhs: UnsafePointer<T>) -> UnsafePointer<T>
func +<T>(lhs: UnsafePointer<T>, rhs: Int) -> UnsafePointer<T>
func +(lhs: Int, rhs: Int) -> Int
func +(lhs: UInt, rhs: UInt) -> UInt
func +(lhs: Int64, rhs: Int64) -> Int64
func +(lhs: UInt64, rhs: UInt64) -> UInt64
func +<T>(lhs: Int, rhs: UnsafeMutablePointer<T>) -> UnsafeMutablePointer<T>
func +<T>(lhs: UnsafeMutablePointer<T>, rhs: Int) -> UnsafeMutablePointer<T>
func +(lhs: Int32, rhs: Int32) -> Int32
func +(lhs: UInt32, rhs: UInt32) -> UInt32
func +(lhs: Int16, rhs: Int16) -> Int16
func +(lhs: UInt16, rhs: UInt16) -> UInt16
func +(lhs: Int8, rhs: Int8) -> Int8
func +(lhs: UInt8, rhs: UInt8) -> UInt8
func +(lhs: Double, rhs: Double) -> Double
func +(lhs: String, rhs: String) -> String
func +(lhs: Float80, rhs: Float80) -> Float80