我有一个函数,它返回一个界限内的整数:
func randomNumber<T: IntegerType>(min: T, max: T) -> T {
let n = max - min + 1
let u = UInt32(n) // Error: Cannot invoke 'init' with an argument of type 'T'
let r = arc4random_uniform(u)
return r + min
}
我不明白为什么这不起作用,因为大多数协议都是符合的。
我必须使
UInt32
变为UnsignedIntegerType
,因为IntegerType
以n
为参数。为什么这个不行?
最佳答案
您需要至少生成两个函数:一个用于SignedIntegerType
,一个用于UnsignedIntegerType
。SignedIntegerType
具有类型强制函数:toIntMax()
和init(_: IntMax)
protocol _SignedIntegerType : _IntegerType, SignedNumberType {
/// Represent this number using Swift's widest native signed integer
/// type.
func toIntMax() -> IntMax
/// Convert from Swift's widest signed integer type, trapping on
/// overflow.
init(_: IntMax)
}
UnsignedIntegerType
还具有类型强制功能:toUIntMax()
和init(_: UIntMax)
protocol _UnsignedIntegerType : _IntegerType {
/// Represent this number using Swift's widest native unsigned
/// integer type.
func toUIntMax() -> UIntMax
/// Convert from Swift's widest unsigned integer type, trapping on
/// overflow.
init(_: UIntMax)
}
使用这些功能,您可以:
func randomNumber<T: UnsignedIntegerType>(min: T, max: T) -> T {
let n = max - min + 1
let u = UInt32(n.toUIntMax())
let r = arc4random_uniform(u)
return T(r.toUIntMax()) + min
}
func randomNumber<T: SignedIntegerType>(min: T, max: T) -> T {
let n = max - min + 1
let u = UInt32(n.toIntMax())
let r = arc4random_uniform(u)
return T(r.toIntMax()) + min
}
但是,我们已经有了方便的内置函数:
func numericCast<T : _UnsignedIntegerType, U : _SignedIntegerType>(x: T) -> U
func numericCast<T : _SignedIntegerType, U : _UnsignedIntegerType>(x: T) -> U
func numericCast<T : _UnsignedIntegerType, U : _UnsignedIntegerType>(x: T) -> U
func numericCast<T : _SignedIntegerType, U : _SignedIntegerType>(x: T) -> U
numericCast
可以简化您的实现:func randomNumber<T: UnsignedIntegerType>(min: T, max: T) -> T {
return min + numericCast(arc4random_uniform(numericCast(max - min + 1)))
}
func randomNumber<T: SignedIntegerType>(min: T, max: T) -> T {
return min + numericCast(arc4random_uniform(numericCast(max - min + 1)))
}
inner
numericCast
将numericCast
转换为T
,outer one将UInt32
转换为UInt32
。现在,这些函数具有完全相同的实现代码:)但是我认为您不能将它们统一为一个函数。