【问题标题】:Capturing values in nested closures在嵌套闭包中捕获值
【发布时间】:2016-10-07 12:48:02
【问题描述】:

在嵌套闭包中使用捕获值的正确语法是什么?

我有以下工作代码,用于使用 zlib 库从整数值计算 CRC32。

func testCrc()
{
    var x: UInt32 = 0xffffffff

    let result = withUnsafePointer(to: &x, {
        $0.withMemoryRebound(to: Bytef.self, capacity: 4) {
            crc32(0, $0, 4)
        }
    })

    XCTAssertEqual(0xffffffff, result)
}

我想创建可以从任何值计算 CRC32 的独立通用函数。为了做到这一点,除了值本身,我还必须计算并传递它的大小,所以我不能像上面代码中那样使用显式大小 - 4。

但我无法找到正确的语法来将计算的大小传递给内部闭包。

func calculateCrc32<T>(_ crc: UInt, value: inout T) -> UInt
{
    let size = MemoryLayout.size(ofValue: value)
    let result = withUnsafePointer(to: &value, {
        $0.withMemoryRebound(to: Bytef.self, capacity: size) {
            crc32(crc, $0, size) // error
        }
    })
    return result
}

上面的代码显示了参数$0的相当混乱的编译器错误:

无法将“UnsafeMutablePointer<_>”类型的值转换为预期值 参数类型“UnsafePointer!”

令人困惑,因为如果我将 crc32(crc, $0, size) 替换为 crc32(crc, $0, 4) 编译器不会抱怨,并且函数对于大小为 4 字节的值正常工作。

如何解决上述问题?

【问题讨论】:

    标签: swift closures swift3


    【解决方案1】:

    错误信息具有误导性。您的代码几乎是正确的, “唯一”问题是crc32() 的最后一个参数,它需要 成为uInt:

    func calculateCrc32<T>(_ crc: UInt, value: inout T) -> UInt
    {
        let size = MemoryLayout.size(ofValue: value)
        let result = withUnsafePointer(to: &value, {
            $0.withMemoryRebound(to: Bytef.self, capacity: size) {
                crc32(crc, $0, uInt(size))
            }
        })
        return result
    }
    

    如果您调用crc32(crc, $0, 4),那么“整数文字”4 作为最后一个参数传递,编译器推断它的类型 如uInt 以匹配函数定义。

    它不能用crc32(crc, $0, size) 编译,因为 Swift 可以 不是在类型之间隐式转换

    或者,使用numericCast(),这是一个通用函数,可以在不同的有符号和无符号整数类型之间进行转换(并在溢出时捕获)。

    我还建议改为创建值的局部变量副本 使用inout 参数,这样更容易调用 功能:

    func calculateCrc32<T>(_ crc: UInt, value: T) -> UInt {
        var value = value
        let size = MemoryLayout.size(ofValue: value)
        let result = withUnsafePointer(to: &value, {
            $0.withMemoryRebound(to: Bytef.self, capacity: size) {
                crc32(crc, $0, numericCast(size))
            }
        })
        return result
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多