通用类型的扩展名'UnsafeMutablePointer <uint8>`

时间:2016-06-22 20:35:44

标签: swift generics unsafe-pointers

我想为UnsafeMutablePointer创建一个仅影响UnsafeMutablePointer<UInt8> ...

的扩展程序

我理解这些说明是相关的,但我不确定如何:

  

扩展泛型类型时,不提供类型参数列表作为扩展定义的一部分。相反,原始类型定义中的类型参数列表在扩展的主体中可用,原始类型参数名称用于引用原始定义中的类型参数。

基本上,我正在尝试使用这种方法:

func toSwift(length: Int) -> [Int] {
    var retVal : [Int] = []
    for i in 0..<length {
        retVal.append(Int(self[i]))
    }
    return retVal
}

在没有self作为参数的情况下对UnsafeMutablePointer<UInt8>采取行动......这可能吗?

2 个答案:

答案 0 :(得分:3)

Swift 3.1更新

从Swift 3.1(Xcode 8.3 beta版本)开始,现在支持具体的相同类型要求。你现在可以说:

extension UnsafeMutablePointer where Pointee == UInt8 {
    func asArray(withLength length: Int) -> [Int] {
        return UnsafeBufferPointer(start: self, count: length).map(Int.init)
    }
}

Pre Swift 3.1

可以这样做 - 尽管它不是特别好。您必须创建新协议才能标记&#39; UInt8类型,然后将您的扩展名约束到该协议。它也不允许您轻松指定Int(...)初始化程序可以进行_UInt8Type输入 - 您必须实施一个hacky&#39; shadow&#39;这样做的方法。

protocol _UInt8Type {
    func _asInt() -> Int
}
extension UInt8 : _UInt8Type {
    func _asInt() -> Int {
        return Int(self)
    }
}

// Change 'Pointee' to 'Memory' for Swift 2
extension UnsafeMutablePointer where Pointee : _UInt8Type {
    func asArray(withLength length:Int) -> [Int] {
        return UnsafeBufferPointer(start: self, count: length).map{$0._asInt()}
    }
}

总而言之,我更喜欢保持这种完全通用,并与@AMomchilov's solution一起使用。我只是为了完成而添加了这个。

虽然值得注意的是,已经提出对扩展(extension Type where Generic == SomeType)提出具体的相同类型要求as a part of the Swift Generics Manifesto - 所以希望这将在未来的Swift版本中实现。< / p>

答案 1 :(得分:2)

目前,您只能对协议执行此操作,而不能对特定的类或结构执行此操作。你可以创建一个伪协议并用它扩展你的类/结构,就像originaluser2's answer一样。

但是,我没有看到不保留此代码通用的理由。你怎么看待这个?

extension UnsafeMutablePointer {
    func toArray(withLength length: UInt) -> [Memory] { //Change "Memory" to "Pointee" in Swift 3
        return Array(UnsafeBufferPointer(start: self, count: Int(length)))
    }
}