我有一个函数,它返回一个界限内的整数:

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,因为IntegerTypen为参数。
为什么这个不行?

最佳答案

您需要至少生成两个函数:一个用于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)))
}

innernumericCastnumericCast转换为T,outer one将UInt32转换为UInt32
现在,这些函数具有完全相同的实现代码:)但是我认为您不能将它们统一为一个函数。

08-25 15:45