You write "all numeric types", but based on a 0.5 multiplication, this answer is based on the assumption that you are referring to commonly used floating point types ( Double , Float , CGFloat ).
You can create a custom protocol that displays the * function (for multiplication by Self values), as well as an initializer on FloatLiteralType and matches Double , Float and CGFloat this protocol. The * function, as well as the initializer, are already implemented for these three types, so the correspondence simply explicitly tells the compiler that these types really match your user protocol.
eg.
protocol MyFloatingPointTypes { func *(lhs: Self, rhs: Self) -> Self init(_: FloatLiteralType) } extension Double : MyFloatingPointTypes {} extension Float : MyFloatingPointTypes {} extension CGFloat : MyFloatingPointTypes {} func half<T: MyFloatingPointTypes>(value: T) -> T { return value * T(0.5) } var dVal: Double = 10.5 var fVal: Float = 10.5 var cfVal: CGFloat = 10.5 dVal = half(dVal) fVal = half(fVal) cfVal = half(cfVal) print(dVal, fVal, cfVal)
Alternative: complex protocol restriction using FloatLiteralConvertible
As @Hamish writes in his comments below, instead of drawing the initializer using Double ( init(_: FloatLiteralType) in MyFloatingPointTypes , it is better to use an additional type restriction for the general half(...) function instead, holding back the general one (in addition to MyFloatingPointTypes ) before FloatLiteralConvertible :
// lets rename this protocol here, since it no longer has any direct association with floats protocol Multiplicable { func *(lhs: Self, rhs: Self) -> Self } extension Double : Multiplicable {} extension Float : Multiplicable {} extension CGFloat : Multiplicable {} func half<T: protocol<Multiplicable, FloatLiteralConvertible>>(value: T) -> T { return value * 0.5 } // ... same as above
Another (more general) alternative: a complex protocol restriction using IntegerLiteralConvertible
Or, if you want the half function to extend its general "scope" to integer types (as @Hamish also noted, thanks!), You can use the same protocol protocol restriction method as above, but against IntegerLiteralConvertible :
protocol Divisable { func /(lhs: Self, rhs: Self) -> Self } extension Double : Divisable {} extension Float : Divisable {} extension CGFloat : Divisable {} extension Int: Divisable {} func half<T: protocol<Divisable, IntegerLiteralConvertible>>(value: T) -> T { return value / 2 } var dVal: Double = 10.5 var fVal: Float = 10.5 var cfVal: CGFloat = 10.5 var iVal: Int = 11 dVal = half(dVal) fVal = half(fVal) cfVal = half(cfVal) iVal = half(iVal)